如下是iOS7开始支持的background fetch在下载管理中的应用。
1.Target -> Capabilities -> Background Modes,打开开关,勾选 Background fetch
一项。
2.在负责下载管理的 CDDownloadManager
,或是 AppDelegate
中,添加 @property (nonatomic, copy) void (^savedCompletionHandler)();
属性,用于临时存储 application:handleEventsForBackgroundURLSession:completionHandler:
传入的block(详细说明见后文)。
3.在 AppDelegate.m
中添加如下方法:
- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler { NSLog(@"%s",__FUNCTION__); [CDDownloadManager sharedManager].savedCompletionHandler = completionHandler; }
在iOS中,当后台传输结束或是需要认证时,如果你的app不是正在运行的状态,它就会自动在后来重新启动,然后app的 UIApplicationDelegate
会收到 application:handleEventsForBackgroundURLSession:completionHandler:
消息。这个函数中包括导致app启动的session的identifier。你的app应该在用相同的identifier创建后台configuration对象之前,把这个completion handler存下来。新创建的session会自动和正在执行的后台活动关联起来。
4.在 CDDownloadManager.m
,或是其他创建了 NSURLSession
实例的类中,实现如下方法:
- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session { NSLog(@"%s", __FUNCTION__); [self.session getTasksWithCompletionHandler:^(NSArray<NSURLSessionDataTask *> * _Nonnull dataTasks, NSArray<NSURLSessionUploadTask *> * _Nonnull uploadTasks, NSArray<NSURLSessionDownloadTask *> * _Nonnull downloadTasks) { if (downloadTasks.count == 0) { // A. if (self.savedCompletionHandler != nil) { void(^completionHandler)() = self.savedCompletionHandler; self.savedCompletionHandler = nil; // B. [[NSOperationQueue mainQueue] addOperationWithBlock:^{ completionHandler(); // C. UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init]; content.title = @"Calios said:"; content.body = @"Hi, what about enjoy Swift in 2017?"; content.sound = [UNNotificationSound defaultSound]; content.badge = @([[UIApplication sharedApplication] applicationIconBadgeNumber] + 1); UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:5.f repeats:NO]; UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"FiveSecond" content:content trigger:trigger]; UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; [center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) { if (!error) { NSLog(@"add notification request succeed!"); } }]; }]; } } }]; }
对应上段代码的几点说明:
A. 这里的 self.savedCompletionHandler
就是上面在 AppDelegate.m
中被赋值的家伙。
B. 由于提供的completion handler是 UIKIt
的一部分,所以一定要在主线程中调用。
C. 这里的操作是在所有下载完成后弹出一个本地通知,并在console显示一行log。可以根据需求自行更改。 注:
iOS 10之后,本地通知和远程通知相关的接口都移到了 UserNotification
中,API也有很多变化,这里不再赘述,更多详情可参见喵神的 这篇博客
。