转载

Background fetch

如下是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也有很多变化,这里不再赘述,更多详情可参见喵神的 这篇博客 。

原文  http://www.calios.gq/2017/01/10/Background-fetch/
正文到此结束
Loading...