Ios UIWindow&x27;s makeKeyAndVisible和后台任务

Ios UIWindow&x27;s makeKeyAndVisible和后台任务,ios,ios7,uiwindow,Ios,Ios7,Uiwindow,我已将后台任务功能添加到我的应用程序中。这是我的应用程序代理 // AppDelegate.m - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [self setWindow:[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]];

我已将后台任务功能添加到我的应用程序中。这是我的应用程序代理

// AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
    [self setWindow:[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]];
    [self.window setBackgroundColor:[UIColor blackColor]];

    if (application.applicationState != UIApplicationStateBackground) {        
        // Application is launch in because user tap the app icon or from springboard

        if ([application respondsToSelector:@selector(setMinimumBackgroundFetchInterval:)]) {
            [application setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
        }
    } else {
        // Application is launch in background mode
    }

    RootViewController *rootViewController = [[RootViewController alloc] initByDevice];
    [self.window setRootViewController:rootViewController];
    [self.window makeKeyAndVisible];

    return YES;
}

- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {

    [[DataManager instance] updateDataWithMaxAttempt:5 block:^(BOOL success, NSArray *newData) {
        if (success) {
            if ([newData count] > 0) {
                completionHandler(UIBackgroundFetchResultNewData);
            } else {
                completionHandler(UIBackgroundFetchResultNoData);
            }
        } else {
            completionHandler(UIBackgroundFetchResultNoData);
        }
    }];
}
这是我的根视图控制器

// RootViewController.m

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    NSLog(@"Did appear");
    // Do something that I want it to happen only when the application is visible to user
}
当用户点击应用程序图标时,应用程序的工作方式与我预期的一样。我在控制台中看到“确实出现了”,然后事情就如我预期的那样发生了

但是,当应用程序唤醒以执行后台任务(用户看不到)时,
RootViewController的
viewdide出现
仍然因为这一行而收到呼叫

[self.window makeKeyAndVisible];
通过调用makeyAndVisible,它使
RootViewController
可见,即使它只在后台任务中处于唤醒状态。要解决此问题,我必须将此行移动到
applicationIDBecomeActive

- (void)applicationDidBecomeActive:(UIApplication *)application {
    [self.window makeKeyAndVisible];
}
因此,
RootViewController的
视图现在只在应用程序位于前台(用户可见)时才显示
。但是,我担心的是,当应用程序在设备内存中时(无论是活动的还是非活动的)
applicationdidebomeactive
将被多次调用

  • 用户启动应用程序
  • 应用程序从springboard重新激活
  • 设备解锁
  • 结束通话

如果我在应用程序生命周期中多次调用
UIWindow的
makeKeyAndVisible
,是否会出现任何问题?

您可以轻松确保
makeKeyAndVisible
只发生一次:包装它

if (!self.window.keyWindow) {
    [self.window makeKeyAndVisible;
} else if (self.window.hidden) {
    self.window.hidden = NO;
}

我认为
UIAlertView
UIActionSheet
将调用此方法,因为在显示键窗口时,键窗口会发生更改。我认为在
applicationIDBECOMEATIVE
中调用
[self.window makeKeyAndVisible]
不是一个好方法,因为那时可能会有
UIAlertView
显示。@KudoCC感谢您的信息,我以前从来都不知道这件事!你知道如果我显示alertview-->锁定设备-->解锁-->调用[self.window makeKeyAndVisible]会发生什么吗?很难说,这是一个未定义的操作,你可以尝试一下。感谢你的解决方案Henri,我应用了与你的答案类似的东西。顺便问一下,你知道如果我多次调用makeKeyAndVisible会发生什么吗?(就像KudoCC在我的原始问题中的评论一样,他说UIAlertView和UIActionSheet也调用了makeKeyAndVisible)我认为这取决于上下文。连续叫它两次,它可能什么也做不了。我现在不在办公桌上,但很容易检查。在任何情况下,我更喜欢确保我自己需要它,而不依赖于API内部逻辑。因此,简单的包装。