iOS背景使用NSURLSessionConfiguration下载

时间:2018-05-18 08:10:26

标签: ios swift download background

我已经实现了代码,以便在20个批次中下载大小为1-2 MB的块。一旦会话完成了前20个下载请求,它将在会话中设置新的20个请求。我已经在控制台日志中的真实设备上测试了它并找到了它。

default 15:56:03.627080 +0800   xyz __nw_socket_service_writes_block_invoke sendmsg(fd 14, 31 bytes): socket has been closed
default 15:56:03.671468 +0800   mediaserverd    -CMSessionMgr- cmsmHandleApplicationStateChange: CMSession: Client com.xyz with pid '1447' is now Background Suspended. Background entitlement: NO
default 15:56:03.671804 +0800   mediaserverd    1067: pid 1447(xyz)
default 15:56:03.672156 +0800   mediaserverd    3138: sid:0x1a653, xyz(1447), 'prim' new state = Background Task Suspended
default 15:56:03.673578 +0800   locationd   Client com.xyz disconnected
default 15:56:03.694200 +0800   symptomsd   1447 com.xyz: BackgroundTaskSuspended (most elevated: BackgroundTaskSuspended)
default 15:56:03.716198 +0800   symptomsd   Entry, display name com.xyz uuid 02184FD5-F48B-3EF7-B2B6-98AB05145DB9 pid 1447 isFront 0

有时会遇到这个问题。

Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory" UserInfo={NSErrorFailingURLKey`enter code here`

Code = 2与设备资源有关。

我的问题是我们可以在下载批量后下载并请求更多文件。或者后台模式仅适用于正在进行的请求并暂停应用程序,但会继续批量下载已发送任务中提到的文件。

这是BG任务的代码,

  if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_7_1) {
        backgroundConfiguration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:[[NSBundle mainBundle] bundleIdentifier]];
    } else {
        backgroundConfiguration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"downloadmanager"];
    }


backgroundConfiguration.discretionary = YES;
backgroundConfiguration.sessionSendsLaunchEvents = YES;
self.backgroundSession = [NSURLSession sessionWithConfiguration:backgroundConfiguration delegate:self delegateQueue:NSOperationQueue.mainQueue];

在BG任务中添加NSURLRequest的代码,

 NSURLRequest *request = [NSURLRequest requestWithURL:url];
        NSURLSessionDownloadTask *downloadTask;
            downloadTask = [self.backgroundSession downloadTaskWithRequest:request];

AppDelegate中的后台任务处理程序

  func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {

        DownloadManager.shared().backgroundTransferCompletionHandler = completionHandler
        print("background task called")
    }

在BG中发送应用后,代理会在控制台中停止打印日志。我可以看到它已经部分下载了文件。

- (void)URLSession:(NSURLSession *)session
      downloadTask:(NSURLSessionDownloadTask *)downloadTask
      didWriteData:(int64_t)bytesWritten
 totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {

    NSLog(@"Byte downlaoded %lld of %lld ", bytesWritten, totalBytesWritten);

}

3 个答案:

答案 0 :(得分:1)

在后台队列中下载多个请求真是太难了。所以我建议你使用Dispatch Groups。请按照以下步骤操作:
步骤1:您可以在一个Dispatch Groups中对20个请求进行分组,为了使您的请求达到平衡,您可以为每个连接设置最大并发请求队列。我认为2个连接是最好的连接 第2步:使用Dispatch Groups时。它可以在完成所有20个请求后通知,然后您可以为新的20个请求创建另外的Dispatch Groups。

请参阅调度组https://www.allaboutswift.com/dev/2016/7/12/gcd-with-swfit3

答案 1 :(得分:1)

我已经实现了后台会话,以便在后台但以串行方式下载多个文件。

但是要实现此功能存在很多挑战。如果操作系统将更多资源用于其他应用程序,它将优先于该应用程序而不是您的应用程序,因此当您启动后台会话时,您应该将远程超时设置为20分钟以下载文件。 20分钟后,它将导致错误的远程超时,并且将无法在后台下载2 mb的文件,而在前台运行应用程序时,它将无法正常运行。

相反,当应用程序在后台运行时,您会发现在前台模式下仅几秒钟就下载了2 mb的文件,这会在20分钟后引发错误(远程超时)。

这很奇怪。。。我发现有一种解决方案,当您尝试在后台模式下下载文件时,请确保已将设备连接到充电电缆,并且发现下载会很有趣。

尝试一下!!!!!!

如有任何疑问,请告诉我。

答案 2 :(得分:0)

我认为你是在一个队列中下载文件,破坏了会话并尝试在另一个队列中读取它。