在我的应用程序中我有一些NSOperation从在线数据库更新一些核心数据元素,有时更新需要一分钟,当iPhone屏幕锁定时,应用程序进入后台模式,此更新停止,所以我必须重新打开应用程序继续更新,所以我已经搜索了很多堆栈溢出,我找到了一些信息:
beginBackgroundTaskWithExpirationHandler
这是一个来自苹果的方法,当应用程序处于后台模式时,让我们继续执行某项任务,并且我已经这样做了:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
UIApplication *app = [UIApplication sharedApplication];
UIBackgroundTaskIdentifier bgTask;
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
}];
}
现在应用程序在后台继续执行任务,似乎一切正常,所以我的问题是,我使用的这种方法是安全的吗?还是有更好的模式?
感谢
答案 0 :(得分:14)
那不是你怎么做的。您要在后台运行的任何代码都必须正确包装。像这样:
- (void)someMethodToKeepRunningInBackground {
UIBackgroundTaskIdentifier taskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^(void) {
// Uh-oh - we took too long. Stop task.
}];
// Perform task here
if (taskId != UIBackgroundTaskInvalid) {
[[UIApplication sharedApplication] endBackgroundTask:taskId];
}
}
您不能使用UIApplicationDelegate applicationDidEnterBackground:
方法做任何事情。
包含在"后台任务中的任何任务"当应用程序进入后台时,将允许调用继续运行。
这是真正重要的部分 - 任务最多只能达到10分钟。如果它在10分钟后仍在运行,您的应用将被终止。在不正确地终止应用程序之前,到期处理程序会让您在几秒钟内干净地结束任务。
答案 1 :(得分:0)
就我而言,当应用程序进入后台时,我必须点击服务到后端。我是这样做的:
func applicationDidEnterBackground(_ application: UIApplication)
{
saveUserSession()
}
// MARK: - Background Tasks
extension AppDelegate
{
func saveUserSession()
{
var backgroundTask: UIBackgroundTaskIdentifier = .invalid
// 1. request some time to execute task in background
backgroundTask = UIApplication.shared.beginBackgroundTask {
guard backgroundTask != .invalid else { return }
// time is out, stop our background task or app will be killed
// my background task is called through `Alamofire`
// so I stop all requests when time is out
Alamofire.Session.default.cancelAllRequests()
}
// 2. start the background task
// the following line (singleton class) calls backend service through `Alamofire`
UserSessionManager.shared.end {
// when finishing service, mark background task as done
UIApplication.shared.endBackgroundTask(backgroundTask)
backgroundTask = .invalid
}
}
}