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

Ash*_*hok 4 background-process multitasking uiapplicationdelegate nsnotificationcenter ios

我觉得在不支持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];
//        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

dub*_*ike 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);

 }
Run Code Online (Sandbox Code Playgroud)

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

void (^fetchCompletionHandler)(UIBackgroundFetchResult);
Run Code Online (Sandbox Code Playgroud)

然后在你的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];


 }
Run Code Online (Sandbox Code Playgroud)

在某个适当的时间,在您的位置委托方法返回后,您调用

fetchCompletionHandler (UIBackgroundFetchResultNewData);
Run Code Online (Sandbox Code Playgroud)

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

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

您可能会将其放入您的app委托应用程序didFinishLaunchingWithOptions方法中.

希望这对你有所帮助.


Kha*_*azi 5

您需要注册以获取通知:

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

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

> Just changed background refresh status because of this notification:NSConcreteNotification 0x165657e0 {name = UIApplicationBackgroundRefreshStatusDidChangeNotification; object = <UIApplication: 0x16668670>}
Run Code Online (Sandbox Code Playgroud)

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

在回顾WWDC会话时,他们说这在DP种子1中不可用。我不确定这是否现在不是应用程序委托方法,因为他们没有使用它或这是他们的意图,因为这种方法更可能被使用在应用程序委托之外(在您自己的模型或VC中)以侦听并适应更改的应用程序后台刷新特权。在后一种情况下,向注册者发出通知更为合理。

希望这可以帮助。

更新:根据WWDC 2013 Core位置视频,要在后台工作的位置更新必须从前台开始。因此,这意味着一旦用户关闭了应用程序的后台刷新,位置更新就会停止,唯一会重新启动位置更新的就是在前台重新启动位置更新!在这种情况下,委托将无用,因为它在后台时无法重新启动位置更新。这是设计使然。