【问题标题】:UIStatusBar Appearance with Multiple Windows带有多个窗口的 UIStatusBar 外观
【发布时间】:2014-05-28 15:08:43
【问题描述】:

首先,我的应用设置:

应用程序的大多数视图控制器都存在于您的标准导航控制器层次结构中,但我在主应用程序窗口上还有第二个窗口,它承载一个视图控制器 (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:]) 不是此应用可接受的解决方案。

【问题讨论】:

  • 除了 swizzling 还有其他解决方案吗?

标签: ios uiviewcontroller uiwindow uistatusbar


【解决方案1】:

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

我能够通过调出UIViewControllersetNeedsStatusAppearanceUpdate 的实现来解决这个问题,因为它知道通知视图控制器的窗口。

@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

这有点老套——我尽量避免混乱——但它允许状态栏外观 API 按原样工作,而不需要所有其他视图控制器都知道NotificationVC

【讨论】:

    【解决方案2】:

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

    [vc1 setNeedsStatusBarAppearanceUpdate]
    

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

    [self setNeedsStatusBarAppearanceUpdate]
    

    当您想切换到另一个 ViewController 的布局时,您可以在该视图控制器上调用 setNeedsStatusBarAppearanceUpdate

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

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

    【讨论】:

    • 问题是 - 这不起作用。我在我的问题中说,setNeedsStatusBarAppearanceUpdate 在从主窗口(不是顶部窗口)中的 VC 调用时无效。
    • 哦,我真的很抱歉。我需要更仔细地阅读。尝试在保存通知控制器的UIWindow 上调用makeKeyAndVisible
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-26
    • 2011-11-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多