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

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

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

- (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]; // } } } 

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

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

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

///具有“获取”后台模式的应用程序可以有机会在后台获取更新的内容,或者在方便系统时获取。 在这些情况下将调用此方法。 您应该在完成该操作后立即调用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); } 

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

 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方法中。

希望这会对你有所帮助。

您需要注册通知:

 [[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 = } 

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

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

希望这可以帮助。

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