我觉得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工程师对此通知用法有其他/有限的意图。请指教。
答案 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位置视频,您要在后台运行的位置更新必须从前台开始。所以这意味着一旦用户关闭应用程序的后台刷新,位置更新将停止,并且唯一重新启动位置更新的事情是重新启动前台的位置更新!在这种情况下,委托将没有用,因为它在后台无法重新启动位置更新。这是设计的。