具有多个Windows的UIStatusBar外观

时间:2014-05-28 15:08:43

标签: ios uiviewcontroller uiwindow uistatusbar

首先,我的应用设置:

大多数应用程序的视图控制器都存在于您的标准导航控制器层次结构中,但我还在主应用程序窗口上有第二个窗口,该窗口托管一个视图控制器(NotificationVC)。如果NotificationVC正在显示通知,它会更改状态栏样式以与通知形成对比,但否则会将样式推迟到主窗口的根视图控制器。

我的问题是主窗口中的更改通常触发状态栏外观更新(推送,弹出或呈现视图控制器,或调用-[UIViewController setNeedsStatusBarAppearanceUpdate]没效果

以下是NotificationVC的相关代码:

@implementation NotificationVC

- (UIStatusBarStyle)preferredStatusBarStyle
{
    if (self.isShowingNotification)
    {
        if (self.notificationView.hasDarkBackground)
        {
            return UIStatusBarStyleLightContent;
        }
        else
        {
            return UIStatusBarStyleDefault;
        }
    }
    else
    {
        return [[UIApplication sharedApplication].delegate window].rootViewController.preferredStatusBarStyle;
    }
}

@end

如何让状态栏从主窗口中的一个视图控制器更新?

注意:手动设置状态栏外观(-[UIApplication setStatusBarStyle:])不适用于此应用。

2 个答案:

答案 0 :(得分:1)

这似乎是对UIViewController部分的优化 - 如果它不在顶部窗口中,则不会触发更新。

我能够通过调出UIViewController setNeedsStatusAppearanceUpdate的{​​{1}}实现来解决这个问题,因为知道了通知视图控制器的窗口。

@interface UIViewController (NotificationWindow)

@end

@implementation UIViewController (NotificationWindow)

+ (void)load
{
    Method original = class_getInstanceMethod([UIViewController class], @selector(setNeedsStatusBarAppearanceUpdate));
    Method swizzled = class_getInstanceMethod([UIViewController class], @selector(swiz_setNeedsStatusBarAppearanceUpdate));
    method_exchangeImplementations(original, swizzled);
}

- (void)swiz_setNeedsStatusBarAppearanceUpdate
{
    UIWindow *topWindow = [UIApplication sharedApplication].windows.lastObject;

    if (![self.view.window isEqual:topWindow] && [topWindow.rootViewController isKindOfClass:[NotificationVC class]])
    {
        [[[UIApplication sharedApplication].windows.lastObject rootViewController] swiz_setNeedsStatusBarAppearanceUpdate];
    }
    else
    {
        [self swiz_setNeedsStatusBarAppearanceUpdate];
    }
}

@end

它有点hacky - 我试图避免调配 - 但它允许状态栏外观API按原样工作,而不需要每个其他视图控制器都知道NotificationVC

答案 1 :(得分:-1)

假设您在屏幕上有3个视图控制器,vc1 vc2 vc3,它们实现preferredStatusBarStyle具有不同的外观。为了使状态栏具有vc1设置的外观,需要调用:

[vc1 setNeedsStatusBarAppearanceUpdate]

当然,ViewController也可以自动触发:

[self setNeedsStatusBarAppearanceUpdate]

如果要切换到另一个ViewController的布局,请在该视图控制器上调用setNeedsStatusBarAppearanceUpdate

作为额外的奖励,您可以为这些更改设置动画:

[UIView animateWithDuration:0.3 animations:^{
    [self setNeedsStatusBarAppearanceUpdate];
}];