苹果ios后台执行示例
Posted
技术标签:
【中文标题】苹果ios后台执行示例【英文标题】:Apple's background execution example for ios 【发布时间】:2017-08-24 01:44:09 【问题描述】:苹果给this of background execution:
- (void)applicationDidEnterBackground:(UIApplication *)application
bgTask = [application beginBackgroundTaskWithName:@"MyTask"
expirationHandler:^
// Clean up any unfinished task business by marking where you
// stopped or ending the task outright.
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
];
// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
// Do the work associated with the task, preferably in chunks.
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
);
这个示例对我来说从来没有多大意义,我已经看到它被复制到许多后台应用程序示例中。
首先没有意义的是expirationHandler中的这两行:
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
bgTask 在块中捕获时似乎没有值。编译器这样抱怨。然后在 dispatch_async 下面的示例中显示了相同的两行。我希望它在 dispatch_async 中,但不在块中。谁能解释为什么我们在块中有这些行?
beginBackgroundTaskWithName 的文档还说“标志着一个新的长期运行的后台任务的开始。”它究竟是如何做到的?什么定义了任务?块范围内是否有任何代码?
【问题讨论】:
It seems like bgTask won't have a value when captured in the block.
为什么不呢?苹果还声明:The bgTask variable is a member variable of the class that stores a pointer to the current background task identifier and is initialized prior to its use in this method.
您可能将后台任务标识符与块混淆了。因此,您可能已经在不持久的范围内声明了标识符。标识符应该在 AppDelegate 中声明为成员变量,只要您的应用程序还活着,它就会一直存在。这就是为什么过期处理程序和 dispatch_async 都可以访问它而无需“复制它”。
@Pochi,不,我没有将标识符与块 ^ 混淆。我所做的是不小心在本地范围内声明它并离开 __block 产生警告“变量'bgTask'在被块捕获时未初始化',但我可能不应该像你说的那样在本地范围内声明它。我引用了这个:hayageek.com/ios-background-task
@william:是的,感谢您指出这一点。
【参考方案1】:
bgTask = [application beginBackgroundTaskWithName:@"MyTask" expirationHandler:]
告诉 iOS 你的应用程序正在启动一个新的后台任务。 iOS 不关心哪个代码构成了任务,它只知道它需要给你的应用更多的时间在后台执行。
此行执行后,bgTask
将包含新的后台任务标识符。
当你的后台任务完成后,你再调用[application endBackgroundTask:bgTask];
,iOS知道你的应用已经完成了指定的后台任务,可能不需要更多的后台执行时间(你可能还有其他由beginBackgroundTaskWithName:expirationHandler
发起的后台任务优秀)。
行:
bgTask = UIBackgroundTaskInvalid;
只是家务;如果省略此行,不会发生任何不良情况,但 bgTask
将包含无效标识符。
如果您在应用的后台时间到期之前未调用endBackgroundTask
,则将调用到期处理程序块。
在到期处理程序中,bgTask
将具有调用 beginBackgroundTaskWithName:expirationHandler
时分配的值,因此这是传递给 endBackgroundTask
的值,再次分配 UIBackgroundTaskInvalid
只是做家务
【讨论】:
所以纠正我:从 iOS 应用程序中的任何位置调用的任何方法通常都会在主线程中执行,除非调用 beginBackgroundTaskWithName 在这种情况下,之后调用的任何方法都将在后台执行,直到 endBackgroundTask叫做。如果 endBackgroundTask 在 beginBackgroundTaskWithName 之后的一定时间内没有被调用,那么 iOS 将终止应用程序。这就是为什么在 exp 处理程序中第二次调用 endBackgroundTask 的原因,以防后台任务没有在我阅读并注意到自己大约 10 分钟的分配时间内完成。 这与您的代码在哪个线程上执行无关。它只是通知您的应用程序想要在后台继续执行任务;通常一个应用程序会在它进入后台后不久被暂停。您的应用在终止前总共有 180 秒的后台执行时间可用。 我仍然不清楚如果 beginBackgroundTaskWithName/endBackgroundTask 对以不同的方法调用会发生什么。例如。在 locationManager:(CLLocationManager *)manager didUpdateLocations 和 applicationDidEnterBackground: 中,我不清楚从 applicationDidEnterBackground 调用重复的 NSTimer。 IE。如果我在没有先调用 beginBackgroundTaskWithName 的情况下调用它,则在应用返回活动状态之前计时器不会触发,但如果我先调用 beginBackgroundTaskWithName,它将无限期运行。 只要一个后台任务没有结束,你的应用就会继续运行,直到达到后台执行时间限制或所有任务都结束。只有在 Xcode 下运行时,计时器才会无限期运行。在正常执行下,您的应用程序将在后台时间 180 秒后终止(当backgroundTimeRemaining
达到 0 时)。在 Xcode 下,当 backgroundTimeRemaining
达到 0 时,您的应用程序会继续运行。
不,我的应用程序在后台运行长达数小时。仅供参考,它具有实时位置共享功能,并且要发送位置数据,它还需要保持网络连接。如果不重置此 iOS 终止时钟,十分钟是我测量的时间。以上是关于苹果ios后台执行示例的主要内容,如果未能解决你的问题,请参考以下文章