简体   繁体   English

如果应用程序已终止,将调用performFetchWithCompletionHandler

[英]Will performFetchWithCompletionHandler be called if the app has been terminated

It's surprisingly difficult to find a definitive answer to this; 很难找到明确的答案; couldn't find it mentioned in the Apple documentation and couldn't find a definite yes/no after searching past questions. 在Apple文档中找不到它,在搜索过去的问题后找不到肯定的是/否。

The question is simple - if the app requests a background fetch to be performed after N time, then the user terminates the app. 问题很简单 - 如果应用程序请求在N次之后执行后台提取,则用户终止应用程序。 Will the OS still launch the app into the background to perform the background fetch? 操作系统是否仍会将应用程序启动到后台以执行后台获取?

Okay, once again background modes cause confusion. 好的,背景模式再一次引起混乱。 No offense to the other people trying to help, but this is more complicated than it seems . 其他人试图帮助没有冒犯,但这比看起来更复杂

First of all: This is out of date, as Sausage guessed in the comments. 首先: 已经过时了,正如Sausage在评论中所猜测的那样。 I know this for a fact, because the section about VoIP apps is still explaining the "old way" to do this, with a handler that gets called periodically. 我知道这是事实,因为有关VoIP应用程序的部分仍在解释执行此操作的“旧方法”,并且会定期调用处理程序。 I investigated this a bit for this answer , so I suggest you go and read that. 对此答案进行了一些调查,所以我建议你去看看。 The important lesson for this case here is that iOS makes a distinction between an app being terminated by the user or by the system, plus it also plays a role whether the phone was rebooted or not. 这个案例的重要教训是,iOS区分了由用户或系统终止的应用程序,而且无论手机是否重新启动,它都会起作用。

So to sum this (and your question) up you basically want to know whether this part of the above, outdated documentation is still correct word for word: 所以总结这个(以及你的问题)你基本上想知道上述过时文档的这一部分是否仍然是正确的:

In most cases, the system does not relaunch apps after they are force quit by the user. 在大多数情况下,系统在用户强行退出后不会重新启动应用程序。 One exception is location apps, which in iOS 8 and later are relaunched after being force quit by the user. 位置应用程序是一个例外,它在iOS 8及更高版本中被用户强行退出后重新启动。 In other cases, though, the user must launch the app explicitly or reboot the device before the app can be launched automatically into the background by the system. 但是,在其他情况下,用户必须明确启动应用程序或重新启动设备,然后系统才能将应用程序自动启动到后台。 When password protection is enabled on the device, the system does not launch an app in the background before the user first unlocks the device. 在设备上启用密码保护后,系统不会在用户首次解锁设备之前在后台启动应用程序。

Apple: Understanding When Your App Gets Launched into the Background Apple: 了解您的应用程序何时启动到后台

I thoroughly investigated the rest of the docs, but did not find any definite answer, so it unfortunately boils down to what dan already suggested: Test it. 我彻底调查了其余的文档,但没有找到任何明确的答案,所以不幸的是归结为丹已经建议:测试它。 My gut feeling is that the documentation is still correct in that regard, though (as said what's not is the VoIP stuff). 我的直觉是文档在这方面仍然是正确的(尽管说不是VoIP的东西)。 I say that because the UI in the Settings app calls the feature "Background App Refresh", so users are probably supposed to understand that an app having this permission won't refresh when they "push" them out of background (ie home button -> swipe it out). 我之所以这么说,是因为“设置”应用中的用户界面调用了“后台应用刷新”功能,因此用户可能应该了解具有此权限的应用在将其“推”出背景时(即主页按钮 - 不会刷新) >把它滑出来)。 For regular users, apps are either quit (not in the task manager at all), in the foreground (using them) or in background (they're in the task manager and another app is in foreground and/or the phone is locked). 对于普通用户,应用要么退出(根本不在任务管理器中),在前台(使用它们)或在后台(它们在任务管理器中,而另一个应用程序在前台和/或手机已锁定) 。


To really test this you'd have to write an app and actually carry it around a bit (I assume at least two days) in each condition. 要真正测试这个,你必须编写一个应用程序并在每种情况下实际携带它(我假设至少两天)。 First while it is in background (the OS should periodically let it fetch, as you probably know this can also be triggered in Xcode) and then while it is force-quit. 首先它是在后台(操作系统应该定期让它获取,因为你可能知道这也可以在Xcode中触发)然后在强制退出时。 The problem is to verify that it fetched stuff. 问题是验证它是否取出了东西。 I'd go with a logfile that can be shared via iTunes. 我会使用可以通过iTunes共享的日志文件。 I have typed up some code for this: 我为此输入了一些代码:

-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
    NSLog(@"We're awake! Booyah!");

    NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:config
                                                          delegate:nil
                                                     delegateQueue:[NSOperationQueue mainQueue]];
    NSMutableURLRequest *request = [NSMutableURLRequest new];
    request.HTTPMethod = @"GET";
    request.URL = [NSURL URLWithString:@"https://www.google.com"];
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request
                                            completionHandler:^(NSData * _Nullable data,
                                                                NSURLResponse * _Nullable response,
                                                                NSError * _Nullable error) {
                                                NSDate *now = [NSDate date];
                                                NSString *toLog = [NSString stringWithFormat:@"%@ - fetched\n",
                                                                   [now description]];
                                                [self updateTestDocumentWithString:toLog];
                                                NSLog(@"Yay, done!");
                                                completionHandler(UIBackgroundFetchResultNewData);
                                            }];
    [task resume];
}

- (void)updateTestDocumentWithString:(NSString *)toAppend {
    NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
    NSString *filePath = [[docDir stringByAppendingPathComponent:@"logfile.txt"] copy];
    if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
        if (![[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil]) {
            NSLog(@"We're effed...");
            return;
        }
    }
    NSFileHandle *file = [NSFileHandle fileHandleForUpdatingAtPath:filePath];
    if (!file) {
        NSLog(@"We're effed again...");
        return;
    }
    [file seekToEndOfFile];
    // ensure this is never nil
    [file writeData:[toAppend dataUsingEncoding:NSUTF8StringEncoding]];
    [file closeFile];
}

This would go into the app delegate, and don't forget to add the Application supports iTunes file sharing boolean setting in your app's plist. 这将进入app委托,并且不要忘记在应用程序的plist中添加Application supports iTunes file sharing布尔设置。 I will leave this running on my development device for a bit and check the logfile, eventually reporting back here. 我会在我的开发设备上运行一段时间并检查日志文件,最后报告回来。 Feel free to test it yourself, too. 也可以自己测试一下。

EDIT: 编辑:

https://devforums.apple.com/message/873265#873265 (login required) https://devforums.apple.com/message/873265#873265 (需要登录)

Also keep in mind that if you kill your app from the app switcher (ie swiping up to kill the app) then the OS will never relaunch the app regardless of push notification or background fetch. 另外请记住,如果你从应用程序切换器中删除你的应用程序(即向上滑动以杀死应用程序),那么无论推送通知或后台获取,操作系统都不会重新启动应用程序。 In this case the user has to manually relaunch the app once and then from that point forward the background activities will be invoked. 在这种情况下,用户必须手动重新启动应用程序一次,然后从该点开始,将调用后台活动。 - pmarcos - pmarcos

That post was by an Apple employee so I think i can trust that this information is correct. 该帖子是由Apple员工发布的,所以我认为我可以相信这些信息是正确的。


OLD answer: 老答案:

According to this answer wrote by a top user: iOS background fetch : your app won't be woken up again. 根据顶级用户写的这个答案: iOS背景提取 :你的应用程序不会再被唤醒。

Make sure you're not killing the app (ie by double tapping on the home button and swiping up on your app for force the app to terminate). 确保你没有杀死应用程序(即双击主页按钮并向上滑动你的应用程序以强制终止应用程序)。 If the app is killed, it will prevent background fetch from working correctly. 如果应用程序被终止,则会阻止后台获取正常工作。

It really doesn't make sense for it to be woken up...it kinda invalidates the user killing the app. 它被唤醒真的没有意义......它有点使用户杀死应用程序无效。

Having that said there are different ways a terminated/force quit app can be launched again: 有了这个说,有不同的方式可以再次启动终止/强制退出应用程序:

  • Tapping on a notification. 点击通知。
  • Tapping on the app icon. 点击应用程序图标。
  • Using openUrl to open your app from another app. 使用openUrl从其他应用程序打开您的应用程序。
  • If you use PushKit ...then your app would be launched. 如果您使用PushKit ...那么您的应用程序将会启动。 Imagine if had a VOIP app eg Skype, WhatsApp and a friend was calling you but you had have force-quit the app, you wouldn't receive calls. 想象一下,如果有一个VOIP应用程序,例如Skype,WhatsApp和一个朋友打电话给你,但你已经强制退出应用程序,你就不会接到电话。 For more see here . 有关详情,请参阅此处
  • Location updates either through use of region monitoring or the significant-change location service. 通过使用区域监控重要更改位置服务更新位置。 See this answer and make sure to read this entire page from Apple docs. 请参阅此答案 ,并确保从Apple文档中阅读整个页面

  • Rebooting the device would also undo anything blocked through force-quit 重新启动设备也会撤消通过强制退出阻止的任何内容

Reading the Apple documentation here I found this text snippet which should explain your question: 这里阅读Apple文档我发现这个文本片段可以解释你的问题:

The techniques offered by iOS fall into three categories: iOS提供的技术分为三类:

  Apps that start a short task in the foreground can ask for time to finish that task when the app moves to the background. **Apps that initiate downloads in the foreground can hand off management of those downloads to the system, thereby allowing the app to be suspended or terminated while the download continues.** Apps that need to run in the background to support specific types of tasks can declare their support for one or more background execution modes. 

The second option is exactly about downloading the data, which can be delegated to the system even if the can be terminated. 第二个选项正是关于下载数据,即使可以终止数据也可以委托给系统。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 应用终止后继续NSURLConnection - Continue a NSURLConnection after the App has been terminated 有没有办法通知服务器该应用程序已被终止? - Is there a way to notify the server that the app has been terminated? 应用终止后发送本地通知 - Sending local notifications after the app has been terminated 应用终止后删除本地通知 - Removing Local Notifications when app has been terminated 应用终止后无法处理本地通知 - Unable to Handle Local Notification when app has been terminated 如果在设置中禁用了后台应用刷新,是否会调用application:performFetchWithCompletionHandler :? - Does application:performFetchWithCompletionHandler: get called if Background App Refresh is disabled in settings? 如果应用程序已从iOS中从后台删除,将会调用performFetchWithCompletionHandler吗? - will performFetchWithCompletionHandler get called if the app got removed from background in iOS? 如何检测股票音乐应用程序是否已终止? - How can I detect if the stock music app has been terminated? 应用终止后,使用NSNotification在UIViewController中处理UILocalNotification - Handle UILocalNotification in UIViewController using NSNotification after the app has been terminated 终止后,通过推送通知启动应用程序 - Launch an app with push notification after it has been terminated
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM