Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/106.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 具有多个窗口的UIStatusBar外观_Ios_Uiviewcontroller_Uiwindow_Uistatusbar - Fatal编程技术网

Ios 具有多个窗口的UIStatusBar外观

Ios 具有多个窗口的UIStatusBar外观,ios,uiviewcontroller,uiwindow,uistatusbar,Ios,Uiviewcontroller,Uiwindow,Uistatusbar,首先,我的应用程序的设置: 大多数应用程序的视图控制器都存在于您的标准导航控制器层次结构中,但我在主应用程序窗口上还有第二个窗口,其中包含一个视图控制器(NotificationVC)。如果NotificationVC正在显示通知,它将更改状态栏样式以与通知形成对比,但在其他情况下,它会将样式延迟到主窗口的根视图控制器 我的问题是,主窗口中通常会触发状态栏外观更新的更改(按下、弹出或显示视图控制器,或调用-[UIViewController setNeedsStatusBarAppearance

首先,我的应用程序的设置:

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

我的问题是,主窗口中通常会触发状态栏外观更新的更改(按下、弹出或显示视图控制器,或调用
-[UIViewController setNeedsStatusBarAppearanceUpdate]
无效

以下是
通知VC
中的相关代码:

@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:
)不是此应用程序可接受的解决方案。

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

我可以通过关闭
UIViewController
setneedssstatusappearanceupdate
实现来解决这个问题,因为我知道通知视图控制器的窗口

@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

它有点黑客化-我尽量避免swizzling-但它允许状态栏外观API按原样工作,而不要求其他所有视图控制器都知道
通知VC

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

[vc1 setNeedsStatusBarAppearanceUpdate]
当然,ViewController也可以自行触发:

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

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

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

问题是——这行不通。我在问题中说,
setNeedsStatusBarAppearanceUpdate
在主窗口(不是顶部窗口)中从VC调用时无效。哦,我真的很抱歉。我需要更仔细地阅读。尝试在保存通知控制器的
ui窗口
上调用
makeKeyAndVisible
,除了swizzling还有其他解决方案吗?