sno*_*und 8 objective-c background-process ios
我正在尝试将一系列文件从iPhone上传到服务器,目的是即使应用程序处于后台或暂停,也会上传这些文件.
我正在使用由它及其系列API 提供的后台传输NSURLSession.
奇怪的是它在两周前完全正常工作.如:
最近几天,我一直在网络模块之外进行一些重构.几天前我再次尝试上传时,只要按下"主页"按钮,上面的步骤(3).当我再次进入应用程序时,文件上传将停止.上传将恢复.
这就好像后台上传甚至不起作用(对于一个文件,更不用说多个文件).
我已多次运行代码,发现它的工作量约为1/50.但其他49次没有.我还检查了以前使用的代码版本(服务器+ iOS),它不再有效 - 或者说,工作很少变化(1/50)
多次完成背景传输和URL会话生命周期的规则,以确保我遵守Apple建议的指导方针,我正在绞尽脑汁想知道什么破坏了,这让人难以理解这是多么不合逻辑 - 我怀疑它是代码实现以外的东西.
所以任何帮助都表示赞赏......
1)在init我的网络类(单例)的方法中,我初始化NSURLSessionConfiguration和NSURLSession:
urlSessionConfigUpload = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:kBACKGROUND_SESSION_CONFIG_ID];
urlSessionConfigUpload.sessionSendsLaunchEvents = YES;
urlSessionConfigUpload.discretionary = YES;
urlSessionConfigUpload.HTTPMaximumConnectionsPerHost = 8;
urlSessionConfigUpload.networkServiceType = NSURLNetworkServiceTypeBackground;
urlSessionConfigUpload.HTTPShouldUsePipelining = NO;
urlSessionConfigUpload.allowsCellularAccess = NO;
urlSession = [NSURLSession sessionWithConfiguration:urlSessionConfigUpload delegate:self delegateQueue:nil];
Run Code Online (Sandbox Code Playgroud)
2)有一种方便的方法叫做实际上传.每个会话只有1个上传任务:
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
[urlRequest setHTTPMethod:@"PUT"];
[urlRequest addValue:@"keep-alive" forHTTPHeaderField:@"Connection"];
[urlRequest addValue:contentType forHTTPHeaderField:@"Content-Type"];
// NB: for upload task in the background, uploadTaskWithRequest:fromData (explicit construction of HTTP POST body) can’t be used,
// must use uploadTaskWithRequest:fromFile (requiring HTTP PUT)
NSURLSessionDataTask *uploadTask = [urlSession uploadTaskWithRequest:urlRequest fromFile:[NSURL fileURLWithPath:filePath]];
[uploadTask resume];
Run Code Online (Sandbox Code Playgroud)
3)在didCompleteWithError委托中,我检查是否所有文件都已上传,如果没有,则移动到下一个文件 - GLOBAL.uploadQueue在那里我保留对我必须上传的所有文件的引用,GLOBAL.uploadQueueIndexNextFile
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
didCompleteWithError:(nullable NSError *)error
{
if ((error == nil && (GLOBAL.uploadQueueIndexNextFile < GLOBAL.uploadQueue.count - 1)) {
// Not on last file, increment counter, start upload of next file
speedLoggerResult = [NSString stringWithFormat:@"Transferring %i of %i files", (GLOBAL.uploadQueueIndexNextFile + 1), GLOBAL.uploadQueue.count];
GLOBAL.uploadQueueIndexNextFile++;
[GLOBAL.fileProcessor processNextFileInUploadQueue];
}
}
Run Code Online (Sandbox Code Playgroud)
processNextFileInUploadQueue 准备文件并调用便捷方法上传(上面的(2)).
以下是穴居人调试的一些示例输出(对于文件2 - 4).请注意,一旦应用进入后台,上传就会停止.
注意,我也等了比下面输出中显示的10秒更长的时间.最长的是我离开吃饭(30分钟),回来后上传结束了.一旦应用程序在后台,操作系统就永远不会把它拿起来.
2016-02-21 05:53:01 +0000 | bkgd debug - about to start upload task | queueIndex: 2
2016-02-21 05:53:01 +0000 | in networking | totalBytesSent | 32768 of 233546 | queueIndex: 2
2016-02-21 05:53:01 +0000 | in networking | totalBytesSent | 65536 of 233546 | queueIndex: 2
2016-02-21 05:53:01 +0000 | in networking | totalBytesSent | 98304 of 233546 | queueIndex: 2
2016-02-21 05:53:01 +0000 | in networking | totalBytesSent | 131072 of 233546 | queueIndex: 2
2016-02-21 05:53:01 +0000 | in networking | totalBytesSent | 163840 of 233546 | queueIndex: 2
2016-02-21 05:53:01 +0000 | in networking | totalBytesSent | 196608 of 233546 | queueIndex: 2
2016-02-21 05:53:01 +0000 | in networking | totalBytesSent | 229376 of 233546 | queueIndex: 2
2016-02-21 05:53:01 +0000 | in networking | totalBytesSent | 233546 of 233546 | queueIndex: 2
2016-02-21 05:53:01 +0000 | in networking | didCompleteWithError | queueindex: 2
bkgd debug - processing next file
2016-02-21 05:53:02 +0000 | bkgd debug - about to start upload task | queueIndex: 3
2016-02-21 05:53:02 +0000 | in networking | totalBytesSent | 32768 of 1231286 | queueIndex: 3
2016-02-21 05:53:02 +0000 | in networking | totalBytesSent | 65536 of 1231286 | queueIndex: 3
2016-02-21 05:53:02 +0000 | in networking | totalBytesSent | 98304 of 1231286 | queueIndex: 3
2016-02-21 05:53:02 +0000 | in networking | totalBytesSent | 131072 of 1231286 | queueIndex: 3
2016-02-21 05:53:02 +0000 | in networking | totalBytesSent | 163840 of 1231286 | queueIndex: 3
2016-02-21 05:53:02 +0000 | in networking | totalBytesSent | 196608 of 1231286 | queueIndex: 3
2016-02-21 05:53:02 +0000 | in networking | totalBytesSent | 229376 of 1231286 | queueIndex: 3
2016-02-21 05:53:02 +0000 | in networking | totalBytesSent | 262144 of 1231286 | queueIndex: 3
2016-02-21 05:53:02 +0000 | in networking | totalBytesSent | 294912 of 1231286 | queueIndex: 3
2016-02-21 05:53:02 +0000 | in networking | totalBytesSent | 327680 of 1231286 | queueIndex: 3
2016-02-21 05:53:02 +0000 | in networking | totalBytesSent | 360448 of 1231286 | queueIndex: 3
2016-02-21 05:53:02 +0000 | in networking | totalBytesSent | 387704 of 1231286 | queueIndex: 3
2016-02-21 05:53:02 +0000 | in networking | totalBytesSent | 391392 of 1231286 | queueIndex: 3
2016-02-21 05:53:02 +0000 | in networking | totalBytesSent | 393216 of 1231286 | queueIndex: 3
2016-02-21 05:53:02 +0000 | in networking | totalBytesSent | 425984 of 1231286 | queueIndex: 3
2016-02-21 05:53:02 +0000 | in networking | totalBytesSent | 458752 of 1231286 | queueIndex: 3
2016-02-21 05:53:02 +0000 | in networking | totalBytesSent | 491520 of 1231286 | queueIndex: 3
2016-02-21 05:53:02 +0000 | in networking | totalBytesSent | 524288 of 1231286 | queueIndex: 3
2016-02-21 05:53:02 +0000 | in networking | totalBytesSent | 538768 of 1231286 | queueIndex: 3
2016-02-21 05:53:03 +0000 | in networking | totalBytesSent | 541664 of 1231286 | queueIndex: 3
2016-02-21 05:53:03 +0000 | in networking | totalBytesSent | 550352 of 1231286 | queueIndex: 3
2016-02-21 05:53:03 +0000 | in networking | totalBytesSent | 553248 of 1231286 | queueIndex: 3
2016-02-21 05:53:03 +0000 | in networking | totalBytesSent | 557056 of 1231286 | queueIndex: 3
2016-02-21 05:53:03 +0000 | App went into background.
2016-02-21 05:53:03 +0000 | in networking | totalBytesSent | 564832 of 1231286 | queueIndex: 3
2016-02-21 05:53:03 +0000 | in networking | totalBytesSent | 567728 of 1231286 | queueIndex: 3
2016-02-21 05:53:03 +0000 | in networking | totalBytesSent | 582208 of 1231286 | queueIndex: 3
2016-02-21 05:53:14 +0000 | in networking | totalBytesSent | 585104 of 1231286 | queueIndex: 3
2016-02-21 05:53:14 +0000 | in networking | totalBytesSent | 589824 of 1231286 | queueIndex: 3
2016-02-21 05:53:14 +0000 | in networking | totalBytesSent | 621680 of 1231286 | queueIndex: 3
2016-02-21 05:53:14 +0000 | App came into foreground.
2016-02-21 05:53:14 +0000 | in networking | totalBytesSent | 622592 of 1231286 | queueIndex: 3
2016-02-21 05:53:14 +0000 | in networking | totalBytesSent | 655360 of 1231286 | queueIndex: 3
2016-02-21 05:53:14 +0000 | in networking | totalBytesSent | 688128 of 1231286 | queueIndex: 3
2016-02-21 05:53:14 +0000 | in networking | totalBytesSent | 720896 of 1231286 | queueIndex: 3
2016-02-21 05:53:14 +0000 | in networking | totalBytesSent | 753664 of 1231286 | queueIndex: 3
2016-02-21 05:53:14 +0000 | in networking | totalBytesSent | 786432 of 1231286 | queueIndex: 3
2016-02-21 05:53:14 +0000 | in networking | totalBytesSent | 819200 of 1231286 | queueIndex: 3
2016-02-21 05:53:15 +0000 | in networking | totalBytesSent | 851968 of 1231286 | queueIndex: 3
2016-02-21 05:53:15 +0000 | in networking | totalBytesSent | 884736 of 1231286 | queueIndex: 3
2016-02-21 05:53:15 +0000 | in networking | totalBytesSent | 887632 of 1231286 | queueIndex: 3
2016-02-21 05:53:15 +0000 | in networking | totalBytesSent | 893424 of 1231286 | queueIndex: 3
2016-02-21 05:53:15 +0000 | in networking | totalBytesSent | 917504 of 1231286 | queueIndex: 3
2016-02-21 05:53:15 +0000 | in networking | totalBytesSent | 939224 of 1231286 | queueIndex: 3
2016-02-21 05:53:15 +0000 | in networking | totalBytesSent | 950272 of 1231286 | queueIndex: 3
2016-02-21 05:53:15 +0000 | in networking | totalBytesSent | 970544 of 1231286 | queueIndex: 3
2016-02-21 05:53:15 +0000 | in networking | totalBytesSent | 983040 of 1231286 | queueIndex: 3
2016-02-21 05:53:15 +0000 | in networking | totalBytesSent | 1015808 of 1231286 | queueIndex: 3
2016-02-21 05:53:15 +0000 | in networking | totalBytesSent | 1048576 of 1231286 | queueIndex: 3
2016-02-21 05:53:15 +0000 | in networking | totalBytesSent | 1081344 of 1231286 | queueIndex: 3
2016-02-21 05:53:15 +0000 | in networking | totalBytesSent | 1114112 of 1231286 | queueIndex: 3
2016-02-21 05:53:15 +0000 | in networking | totalBytesSent | 1146880 of 1231286 | queueIndex: 3
2016-02-21 05:53:15 +0000 | in networking | totalBytesSent | 1179648 of 1231286 | queueIndex: 3
2016-02-21 05:53:15 +0000 | in networking | totalBytesSent | 1212416 of 1231286 | queueIndex: 3
2016-02-21 05:53:15 +0000 | in networking | totalBytesSent | 1231286 of 1231286 | queueIndex: 3
2016-02-21 05:53:16 +0000 | in networking | didCompleteWithError | queueindex: 3
bkgd debug - processing next file
2016-02-21 05:53:16 +0000 | bkgd debug - about to start upload task | queueIndex: 4
2016-02-21 05:53:16 +0000 | in networking | totalBytesSent | 32768 of 1278039 | queueIndex: 4
2016-02-21 05:53:16 +0000 | in networking | totalBytesSent | 65536 of 1278039 | queueIndex: 4
2016-02-21 05:53:16 +0000 | in networking | totalBytesSent | 98304 of 1278039 | queueIndex: 4
2016-02-21 05:53:16 +0000 | in networking | totalBytesSent | 131072 of 1278039 | queueIndex: 4
Run Code Online (Sandbox Code Playgroud)
很高兴在这一点上尝试任何事情.谢谢!
application:handleEventsForBackgroundURLSession:completionHandler:操作系统调用后台上传工作时观察到的.当它不起作用时,永远不会发出回叫.
我不确定后台上传的先决条件是操作系统必须先杀死应用程序.如果是这样,在什么条件下会发生这种情况?我们可以提示吗?
如前所述,50次中有49次,操作系统会将应用程序保留在后台,并暂停上传.
小智 3
有一点需要明确的是,你不能在后台长时间运行任何任务,因为苹果不允许你这样做。只有在特殊情况下,苹果才会考虑它。在 iOS 中运行后台服务中得到了最好的解释
现在回到您的实施问题,它只会在后台工作,上传任务是在应用程序处于活动状态且任务尚未完成时启动的。这就是您看到任务在后台运行的 50 次尝试中有 1 次的原因。
现在要解决您的问题,您必须立即启动所有/一堆上传,以便万一应用程序进入后台,您的应用程序仍然能够上传文件。这个精彩的教程解释了与后台传输相关的不同案例。
您也可以尝试AFNetworking分段请求上传。
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:@"http://example.com/upload" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileURL:[NSURL fileURLWithPath:@"file://path/to/image.jpg"] name:@"file" fileName:@"filename.jpg" mimeType:@"image/jpeg" error:nil];
} error:nil];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSURLSessionUploadTask *uploadTask;
uploadTask = [manager
uploadTaskWithStreamedRequest:request
progress:^(NSProgress * _Nonnull uploadProgress) {
// This is not called back on the main queue.
// You are responsible for dispatching to the main queue for UI updates
dispatch_async(dispatch_get_main_queue(), ^{
//Update the progress view
[progressView setProgress:uploadProgress.fractionCompleted];
});
}
completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
if (error) {
NSLog(@"Error: %@", error);
} else {
NSLog(@"%@ %@", response, responseObject);
}
}];
[uploadTask resume];
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3809 次 |
| 最近记录: |