web-dev-qa-db-ja.com

<UITabBarController:0x197870>の外観の遷移を開始/終了するための不均衡な呼び出し

同様の error に遭遇した別のユーザーについてSOを読みましたが、このエラーは別の場合です。

最初にView Controllerを追加したときにこのメッセージを受け取りました。

Unbalanced calls to begin/end appearance transitions for 
<UITabBarController: 0x197870>

アプリの構造は次のとおりです。

5つのView Controllerにリンクされた5タブのTabBarControllerを取得しました。最初の表示タブでは、アプリの紹介としてオーバーレイする新しいView Controllerを呼び出します。

このコードを使用して、紹介ビューコントローラーを呼び出します。

IntroVC *vc = [[IntroVC alloc] init];
[self presentModalViewController:vc animated:YES];
[vc release]; 

このIntroVC View Controllerが表示された後、上記のエラーが表示されます。

追伸私は、xCode 4.2とiOS 5.0 SDKを使用して、iOS 4.3アプリを開発しています。

113
Raptor

周囲のコードをもっと見なければ、明確な答えを出すことはできませんが、2つの理論があります。

  1. UIViewControllerの-​​ 指定された初期化子initWithNibName:bundle: を使用していません。 initの代わりに使用してみてください。

  2. また、selfはTab Bar ControllerのView Controllerの1つである場合があります。常に最上位のView ControllerからView Controllerを提示します。つまり、この場合、Tab Bar ControllerにView Controllerに代わってオーバーレイView Controllerを提示するように依頼します。コールバックデリゲートを実際のView Controllerに保持することはできますが、Tab Bar Controllerを表示して終了する必要があります。

94
Jesper

アニメーションをYESからNOに変更して、このエラーを修正しました。

から:

[tabBarController presentModalViewController:viewController animated:YES];

に:

[tabBarController presentModalViewController:viewController animated:NO];
40
PokerIncome.com

danh による投稿

アプリの初期化が完了する前にモーダルvcを提示することで、この警告を生成できます。つまり、タブ付きアプリケーションテンプレートアプリを起動し、application.didFinishLaunchingの最後の行としてself.tabBarControllerの上にモーダルvcを提示します。警告が表示されます。解決策:スタックを最初に解き放ち、別のメソッドでモーダルvcを提示し、performSelector withDelay:0.0で呼び出します

メソッドをviewWillAppearに移動して、一度だけ実行されるようにガードしてみてください(プロパティを設定することをお勧めします)

16
Peter Lapisu

多くの場合の別の解決策は、UIViewControllers間の遷移がafterでないことを確認することです(---)不適切な(初期化中など)プロシージャが終了すると、

__weak MyViewController *weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
    [weakSelf presentViewController:vc animated:YES];
});

これは、pushViewController:animated:などにも一般的です。

5
mllm

別のView ControllerからログインView Controllerを提示する必要があるときに同じ問題が発生しました。ユーザーが承認されていない場合、別のView ControllerのViewDidLoadメソッドでそれを行いました(承認されていない場合-> presentModalViewController)。 ViewDidAppearメソッドで作成を開始すると、この問題を解決しました。 ViewDidLoadはプロパティを初期化するだけで、その後、実際の表示アルゴリズムが表示されると思います!それが、モーダル遷移を行うためにviewDidAppearメソッドを使用する必要がある理由です!

3
Tolusha

同じ問題がありました。最初のviewDidLoad内のUIViewController内のメソッドを呼び出しました

- (void)viewDidLoad{
    [super viewDidLoad];

    [self performSelector:@selector(loadingView)
               withObject:nil afterDelay:0.5];
}

- (void)loadingView{

    [self performSegueWithIdentifier:@"loadedData" sender:self];
}

2番目のUIViewController内でも、0.5秒の遅延で同じことを行いました。遅延をより高い値に変更した後、正常に機能しました。別のセグエの後にセグエをあまり速く実行できないようです。

3
Alex Cio

タイプミスのためにこの問題が発生しました:

override func viewDidAppear(animated: Bool) {
    super.viewWillAppear(animated)

の代わりに

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

スーパーで「DidAppear」の代わりに「WillAppear」を呼び出していました

2
Adriano Spadoni

サードパーティのコードでこの問題が発生しました。誰かがカスタムTabBarControllerクラスのviewWillAppearとviewWillDisappearの内部にスーパーを設定するのを忘れていました。

- (void) viewWillAppear:(BOOL)animated {

    [super viewWillAppear:animated];
    // code...
}

or

- (void) viewWillDisappear:(BOOL)animated {

    [super viewWillDisappear:animated];
    // code...
}
2
J. Lopes

書いて解決しました

[self.navigationController presentViewController:viewController 
                                        animated:TRUE 
                                      completion:NULL];
2
pankesh

同じ問題に多くの問題がありました。私はこれを解決しました

  1. Storyboad instantiateViewControllerWithIdentifierメソッドを使用してViewControllerを開始します。すなわちIntro *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"introVC"];
  2. [self.tabBarController presentModalViewController : vc animated:YES];

ストーリーボードにViewControllerがありますが、何らかの理由で[[introvc alloc] init];のみを使用してもうまくいきませんでした。

2
Mogambolal

transitioningDelegateを使用している場合(この質問の例ではありません)、modalPresentationStyle.Customに設定します。

Swift

let vc = storyboard.instantiateViewControllerWithIdentifier("...")
vc.transitioningDelegate = self
vc.modalPresentationStyle = .Custom
2
Kof

私は同じ問題を抱えており、他の誰かが同様の何かに遭遇した場合に投稿すると思いました。

私の場合、長押しジェスチャー認識機能をUITableViewControllerに接続していました。

UILongPressGestureRecognizer *longPressGesture = [[[UILongPressGestureRecognizer alloc]
                                                   initWithTarget:self
                                                   action:@selector(onLongPress:)]
                                                  autorelease];
[longPressGesture setMinimumPressDuration:1];
[self.tableView addGestureRecognizer:longPressGesture];

OnLongPressセレクターで、次のView Controllerを起動しました。

- (IBAction)onLongPress:(id)sender {

    SomeViewController* page = [[SomeViewController alloc] initWithNibName:@"SomeViewController" bundle:nil];

    [self.navigationController pushViewController:page animated:YES];

    [page release];

}

私の場合、長押しレコグナイザーが複数回起動し、その結果、「SomeViewController」がスタックに複数回プッシュされたため、エラーメッセージを受け取りました。

解決策は、SomeViewControllerがスタックにプッシュされたことを示すブール値を追加することでした。 UITableViewControllerのviewWillAppearメソッドが呼び出されたときに、ブール値をNOに戻しました。

1
Dale Moore

同じエラーが発生しました。 3つのアイテムを持つタブバーがあり、performSegueWithIdentifierを使用して、タブバーのアイテム2のアイテム1のルートビューコントローラーを無意識に呼び出しようとしました。

発生するのは、View Controllerを呼び出し、数秒後にアイテム2のルートView Controllerに戻り、そのエラーをログに記録することです。

どうやら、アイテムのルートビューコントローラーを別のアイテムに呼び出すことはできません。

したがって、performSegueWithIdentifierの代わりに

[self.parentViewController.tabBarController setSelectedIndex:0];を使用しました

これが誰かを助けることを願っています。

1
Gellie Ann

InSwift 2 +私の作品:

ストーリーボードにUITabBarViewControllerがあり、次のようなselectedIndexプロパティがありました。

enter image description here

しかし、私はそれを削除し、次のように最初のクラスのviewDidLoadメソッドを追加します。

override func viewDidLoad() {
   super.viewDidLoad()
   self.tabBarController?.selectedIndex = 2
}

私は誰かを助けることができると思います。

1
Dasoga

-(void)beginAppearanceTransition:(BOOL)isAppearing animated:(BOOL)animatedと-(void)endAppearanceTransitionがクラスで一緒に作成されることを確認する必要があります。

0
zszen

実際、Pushアニメーションが終了するまで待つ必要があります。そのため、UINavigationControllerを委任し、アニメーションが終了するまでプッシュを防ぐことができます。

- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
    waitNavigation = NO;
}


-(void)showGScreen:(id)gvc{

    if (!waitNavigation) {
        waitNavigation = YES;
        [_nav popToRootViewControllerAnimated:NO];
        [_nav pushViewController:gvc animated:YES];
    }
}
0
ymutlu

同じ問題がありました。開発時に、画面をバイパスしたかった。私は、viewDidLoadでセレクターメソッドを呼び出して、あるView Controllerから別のView Controllerに移動していました。

問題は、別のViewControllerに移行する前に、ViewControllerの移行を完了させる必要があることです。

これで私の問題が解決しました。ViewControllerが別の移行前に移行を完了するために遅延が必要です。

self.perform(#selector(YOUR SELECTOR METHOD), with: self, afterDelay: 0.5)

0
codeedoc

ストーリーボードを使用している場合、新しいView Controllerを表示しているコードをviewDidAppearに配置する必要があることがわかりました。また、「切り離されたView ControllerにView Controllerを表示することはお勧めできません」という警告も取り除きます。

0
Dan Levy

@danhが示唆したように、私の問題はUITabBarControllerの準備ができる前にモーダルvcを提示していたことでした。ただし、View Controllerを表示する前に固定遅延に依存することに不快感を覚えました(テストから、performSelector:withDelay:で0.05〜0.1秒の遅延を使用する必要がありました)。私の解決策は、UITabBarControllerviewDidAppear:メソッドで呼び出されるブロックを追加することです。

PRTabBarController.h:

@interface PRTabBarController : UITabBarController

@property (nonatomic, copy) void (^viewDidAppearBlock)(BOOL animated);

@end

PRTabBarController.m:

#import "PRTabBarController.h"

@implementation PRTabBarController

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    if (self.viewDidAppearBlock) {
        self.viewDidAppearBlock(animated);
    }
}

@end

application:didFinishLaunchingWithOptions:になりました

PRTabBarController *tabBarController = [[PRTabBarController alloc] init];

// UIWindow initialization, etc.

__weak typeof(tabBarController) weakTabBarController = tabBarController;
tabBarController.viewDidAppearBlock = ^(BOOL animated) {
    MyViewController *viewController = [MyViewController new];
    viewController.modalPresentationStyle = UIModalPresentationOverFullScreen;
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
    [weakTabBarController.tabBarController presentViewController:navigationController animated:NO completion:nil];
    weakTabBarController.viewDidAppearBlock = nil;
};
0
johnboiles