同様の 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アプリを開発しています。
周囲のコードをもっと見なければ、明確な答えを出すことはできませんが、2つの理論があります。
UIViewController
の- 指定された初期化子initWithNibName:bundle:
を使用していません。 init
の代わりに使用してみてください。
また、self
はTab Bar ControllerのView Controllerの1つである場合があります。常に最上位のView ControllerからView Controllerを提示します。つまり、この場合、Tab Bar ControllerにView Controllerに代わってオーバーレイView Controllerを提示するように依頼します。コールバックデリゲートを実際のView Controllerに保持することはできますが、Tab Bar Controllerを表示して終了する必要があります。
アニメーションをYESからNOに変更して、このエラーを修正しました。
から:
[tabBarController presentModalViewController:viewController animated:YES];
に:
[tabBarController presentModalViewController:viewController animated:NO];
danh による投稿
アプリの初期化が完了する前にモーダルvcを提示することで、この警告を生成できます。つまり、タブ付きアプリケーションテンプレートアプリを起動し、application.didFinishLaunchingの最後の行としてself.tabBarControllerの上にモーダルvcを提示します。警告が表示されます。解決策:スタックを最初に解き放ち、別のメソッドでモーダルvcを提示し、performSelector withDelay:0.0で呼び出します
メソッドをviewWillAppearに移動して、一度だけ実行されるようにガードしてみてください(プロパティを設定することをお勧めします)
多くの場合の別の解決策は、UIViewController
s間の遷移がafterでないことを確認することです(---)不適切な(初期化中など)プロシージャが終了すると、
__weak MyViewController *weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf presentViewController:vc animated:YES];
});
これは、pushViewController:animated:
などにも一般的です。
別のView ControllerからログインView Controllerを提示する必要があるときに同じ問題が発生しました。ユーザーが承認されていない場合、別のView ControllerのViewDidLoadメソッドでそれを行いました(承認されていない場合-> presentModalViewController)。 ViewDidAppearメソッドで作成を開始すると、この問題を解決しました。 ViewDidLoadはプロパティを初期化するだけで、その後、実際の表示アルゴリズムが表示されると思います!それが、モーダル遷移を行うためにviewDidAppearメソッドを使用する必要がある理由です!
同じ問題がありました。最初の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秒の遅延で同じことを行いました。遅延をより高い値に変更した後、正常に機能しました。別のセグエの後にセグエをあまり速く実行できないようです。
タイプミスのためにこの問題が発生しました:
override func viewDidAppear(animated: Bool) {
super.viewWillAppear(animated)
の代わりに
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
スーパーで「DidAppear」の代わりに「WillAppear」を呼び出していました
サードパーティのコードでこの問題が発生しました。誰かがカスタムTabBarControllerクラスのviewWillAppearとviewWillDisappearの内部にスーパーを設定するのを忘れていました。
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// code...
}
or
- (void) viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
// code...
}
書いて解決しました
[self.navigationController presentViewController:viewController
animated:TRUE
completion:NULL];
同じ問題に多くの問題がありました。私はこれを解決しました
Intro *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"introVC"];
[self.tabBarController presentModalViewController : vc animated:YES];
ストーリーボードにViewControllerがありますが、何らかの理由で[[introvc alloc] init];
のみを使用してもうまくいきませんでした。
transitioningDelegate
を使用している場合(この質問の例ではありません)、modalPresentationStyle
を.Custom
に設定します。
Swift
let vc = storyboard.instantiateViewControllerWithIdentifier("...")
vc.transitioningDelegate = self
vc.modalPresentationStyle = .Custom
私は同じ問題を抱えており、他の誰かが同様の何かに遭遇した場合に投稿すると思いました。
私の場合、長押しジェスチャー認識機能を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に戻しました。
同じエラーが発生しました。 3つのアイテムを持つタブバーがあり、performSegueWithIdentifier
を使用して、タブバーのアイテム2のアイテム1のルートビューコントローラーを無意識に呼び出しようとしました。
発生するのは、View Controllerを呼び出し、数秒後にアイテム2のルートView Controllerに戻り、そのエラーをログに記録することです。
どうやら、アイテムのルートビューコントローラーを別のアイテムに呼び出すことはできません。
したがって、performSegueWithIdentifier
の代わりに
[self.parentViewController.tabBarController setSelectedIndex:0];
を使用しました
これが誰かを助けることを願っています。
-(void)beginAppearanceTransition:(BOOL)isAppearing animated:(BOOL)animatedと-(void)endAppearanceTransitionがクラスで一緒に作成されることを確認する必要があります。
実際、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];
}
}
同じ問題がありました。開発時に、画面をバイパスしたかった。私は、viewDidLoadでセレクターメソッドを呼び出して、あるView Controllerから別のView Controllerに移動していました。
問題は、別のViewControllerに移行する前に、ViewControllerの移行を完了させる必要があることです。
これで私の問題が解決しました。ViewControllerが別の移行前に移行を完了するために遅延が必要です。
self.perform(#selector(YOUR SELECTOR METHOD), with: self, afterDelay: 0.5)
ストーリーボードを使用している場合、新しいView Controllerを表示しているコードをviewDidAppearに配置する必要があることがわかりました。また、「切り離されたView ControllerにView Controllerを表示することはお勧めできません」という警告も取り除きます。
@danhが示唆したように、私の問題はUITabBarController
の準備ができる前にモーダルvcを提示していたことでした。ただし、View Controllerを表示する前に固定遅延に依存することに不快感を覚えました(テストから、performSelector:withDelay:
で0.05〜0.1秒の遅延を使用する必要がありました)。私の解決策は、UITabBarController
のviewDidAppear:
メソッドで呼び出されるブロックを追加することです。
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;
};