web-dev-qa-db-ja.com

ViewWillAppearのナビゲーションバーの色付けはiOS10では遅すぎます

私は奇妙なバグに直面しています。それはiOS10でのみ発生します。

複数の画面を持つアプリケーションがあり、各画面はnavigationBarviewWillAppearに色を付けています。そのため、次の画面に進むと、適切に色付けされます。

ただし、iOS 10でテストすると、前の画面に戻ると突然次の動作が見られます。前の画面が表示されても、navigationBarは前の画面の色のままで、適切な色に点滅します。 viewWillAppearはどういうわけかviewDidAppearのように動作するように見えます。

関連コード:

ViewController:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [ViewControllerPainter Paint:self withBackground:[UIColor whiteColor] andForeground:[UIColor blackColor] andIsLight:true];

}

画家:

+ (void)Paint:(UIViewController *)controller withBackground:(UIColor *)backgroundColor andForeground:(UIColor *)foregroundColor andIsLight:(bool)isLight
{
    controller.navigationController.navigationBar.opaque = true;
    controller.navigationController.navigationBar.translucent = false;
    controller.navigationController.navigationBar.tintColor = foregroundColor;
    controller.navigationController.navigationBar.barTintColor = backgroundColor;
    controller.navigationController.navigationBar.backgroundColor = backgroundColor;
    controller.navigationController.navigationBar.barStyle = isLight ? UIBarStyleDefault : UIBarStyleBlack;
    controller.navigationController.navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName: foregroundColor};
}

これはバグですか?これを修正するために私にできることはありますか?とてもイライラします。

19
Peterdk

iOS 10 SDKリリースノート に従って変更されたものは次のとおりです。

IOS 10では、UIKitは、UINavigationBar、UITabBar、およびUIToolbarのバックグラウンド管理を更新および統合しました。特に、これらのビューの背景プロパティへの変更(背景や影の画像、バースタイルの設定など)により、新しい背景の外観を解決するためにバーのレイアウトパスが開始される場合があります。
特に、これは、-[UIView layoutSubviews]、-[UIView updateConstraints]、-[UIViewController willLayoutSubviews]、-[UIViewController didLayoutSubviews]、-[UIViewControllerupdateViewConstraints内のこれらのバーの背景の外観を変更しようとすることを意味します]、またはレイアウトに応答して呼び出される他のメソッドは、レイアウトループを引き起こす可能性があります。

したがって、問題は、viewWillAppearがレイアウト変更の結果として呼び出されるため、前述のレイアウトループをトリガーしていることのようです。 viewWillAppear stack trace

私の簡単な修正は、popViewControllerAnimatedpushViewControllerをオーバーライドし、navigationBarのサブクラスのUINavigationControllerバックグラウンドを更新することでした。外観は次のとおりです。

override func popViewControllerAnimated(animated: Bool) -> UIViewController? {
    let poppedViewController = super.popViewControllerAnimated(animated)

    // Updates the navigation bar appearance
    updateAppearanceForViewController(nextViewController)

    return poppedViewController
}

override func pushViewController(viewController: UIViewController, animated: Bool) {
    super.pushViewController(viewController, animated: animated)

    // Updates the navigation bar appearance
    updateAppearanceForViewController(viewController)
}

私の推測では、popViewControllerAnimatedpushViewControllerは、レイアウト変更の結果としてOSによって呼び出されるのではなく、タッチイベントによって呼び出されるために機能します。したがって、navigationBarの背景を更新する別の場所を見つけたい場合は、この点に注意してください。

22
Christian

私はこれを次のように修正する必要がありました:

self.navigationController.navigationBarHidden = YES;
self.navigationController.navigationBarHidden = NO;

このようにして、popviewcontrollerまたはpushviewcontrollerをオーバーライドする必要はありません。基本的に、ナビゲーションバーをトリガーして再描画します。

これほど重要な何かを壊す新しいバージョンのOSをプッシュする方法はまだ面倒です。

16
Vlad

willMoveToParentViewControllerを使用してみてください。これは、UINavigationControllerメソッドをオーバーライドするのと同じ効果がありますが、面倒なことはありません。

7
Usman Raza