UIApplicationBackgroundRefreshStatusDidChangeNotification用法没有相应的委托方法

时间:2013-10-07 21:32:59

标签: ios background-process nsnotificationcenter multitasking uiapplicationdelegate

我觉得iOS 7中引入的 UIApplicationBackgroundRefreshStatusDidChangeNotification 在没有支持UIApplication委托方法的情况下几乎没用。因为,当用户为我的应用程序开启后台刷新状态时,不会通知应用程序。

这是我的通知处理程序......

- (void)applicationDidChangeBackgroundRefreshStatus:(NSNotification *)notification
{
    NSLog(@"applicationDidChangeBackgroundRefreshStatus with notification info = %@ and refresh status = %d", notification, UIApplication.sharedApplication.backgroundRefreshStatus);

    if (UIApplication.sharedApplication.backgroundRefreshStatus == UIBackgroundRefreshStatusAvailable) {
//        if ([CLLocationManager locationServicesEnabled]) {
            [self.locationManager startUpdatingLocation];
//        }
    }
}

如上所述,我想在通过app 设置>制作UIBackgroundRegreshStatus 可用时开始更新核心位置一般>后台应用刷新。我觉得在UIApplicationDelegate中应该有一个合适的委托方法让应用知道这个变化,以便App可以重新建立它所需要的一切。

要么我缺少某些东西(预先存在的API),要么Apple SDK工程师对此通知用法有其他/有限的意图。请指教。

2 个答案:

答案 0 :(得分:6)

理想情况下,您永远不必检查该设置。看起来好像你正在以错误的方式背景。通过最小化应用程序,系统将定期唤醒您的应用程序并允许其执行任务。从您的代码中,您想要更新位置。第一个开始就在这里,使用这个委托方法,当应用程序被唤醒以进行后台提取时调用

///具有“获取”后台模式的应用程序可能有机会在后台获取更新的内容,或者在方便系统时获取。在这些情况下将调用此方法。您应该在完成该操作后立即调用fetchCompletionHandler,以便系统可以准确估计其功率和数据成本。 - (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void(^)(UIBackgroundFetchResult result))completionHandler NS_AVAILABLE_IOS(7_0);

这是你如何使用它,在你的应用程序委托实现中,定义方法体如下

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

    NSLog(@"APP IS AWAKE FOR A BACKGROUND FETCH");
    //do all the work you want to do 

//once done, its important to call the completion hadler, otherwise the system will complain
          completionHandler(UIBackgroundFetchResultNewData);

 }

但是,由于您要更新具有自己的委托的位置,因此您只希望在委托返回时调用完成处理程序,而不是在此之前调用。调用完成处理程序将使您的应用程序重新进入休眠状态。由于完成处理程序是块对象,因此它可以像任何其他对象一样传递。一种方法如下:在应用程序委托头文件中,定义一个块对象:

void (^fetchCompletionHandler)(UIBackgroundFetchResult);

然后在你的performFetchWithCompletionHandler中有:

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

    NSLog(@"APP IS AWAKE FOR A BACKGROUND FETCH");
    //do all the work you want to do 
            [self.locationManager startUpdatingLocation];


 }

在适当的时候,在您的位置委托方法返回后,您可以调用

fetchCompletionHandler (UIBackgroundFetchResultNewData);

一定要检查你的fetchCompletionHandler是否是非nill,当nil会立即崩溃你的应用程序时调用它。从这里的苹果文档中了解更多关于块的信息https://developer.apple.com/library/ios/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/WorkingwithBlocks/WorkingwithBlocks.html

还看看调用[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:]; which指定后台提取操作之间必须经过的最短时间。

你可能会把它放到你的app委托应用程序didFinishLaunchingWithOptions方法中。

希望这会对你有所帮助。

答案 1 :(得分:5)

您需要注册通知:

[[NSNotificationCenter defaultCenter]
 addObserverForName:UIApplicationBackgroundRefreshStatusDidChangeNotification
 object: [UIApplication sharedApplication]
 queue:nil
 usingBlock:^(NSNotification* notification){
     NSLog(@"Just changed background refresh status because of this notification:%@",notification);
 }];

如果您的应用程序正在运行,您将获得此输出,然后切换并禁用后台应用程序刷新。

> Just changed background refresh status because of this notification:NSConcreteNotification 0x165657e0 {name = UIApplicationBackgroundRefreshStatusDidChangeNotification; object = <UIApplication: 0x16668670>}

您显然可以选择其他队列。此外,这不必在应用程序委托中。任何类都可以侦听此通知。

回顾WWDC会议,他们说这在DP种子1中不可用。我不确定这是不是现在的应用委托方法,因为他们没有达到它或者他们的意图是因为它更有可能要在app委托之外(在您自己的模型或VC中)使用,以监听并调整为更改的应用程序后台刷新权限。在后一种情况下,通知任何注册它的人都会更有意义。

希望这有帮助。

更新: 根据WWDC 2013 Core位置视频,您要在后台运行的位置更新必须从前台开始。所以这意味着一旦用户关闭应用程序的后台刷新,位置更新将停止,并且唯一重新启动位置更新的事情是重新启动前台的位置更新!在这种情况下,委托将没有用,因为它在后台无法重新启动位置更新。这是设计的。