XXXXOperation是NSOperation的子类,在主函数中,我用AFNetwork实现了文件下载器,有时它在完成块(死代码)处崩溃,崩溃原因是“-[NSURL initFileURLWithPath:] nil字符串参数”。原因是线程在完成执行时退出,但是我不知道为什么?我尝试重现异常,但未成功!有人可以解释吗?谢谢!
@interface XXXXOperation : NSOperation
@property (nonatomic, strong) NSPort *port;
@end
@implementation XXXXOperation
- (void)main
{
@autoreleasepool {
if (self.pluginInfo.pluginId > 0 && self.pluginInfo.downloadUrl.absoluteString.length > 0)
{
self.currentThread = [NSThread currentThread];
NSString *pluginId = self.pluginInfo.pluginId.length > 0 ? self.pluginInfo.pluginId : @"";
NSNumber *pluginVersion = @(self.pluginInfo.pluginVersion);
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration];
configuration.timeoutIntervalForRequest = 20;
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
manager.completionQueue = [RNPluginDownloadHelper getCompletionQueue];
NSMutableSet *acceptableContentTypes = [[NSMutableSet alloc] initWithSet:[(AFHTTPResponseSerializer *)manager.responseSerializer acceptableContentTypes]];
[acceptableContentTypes addObject:@"application/zip"];
NSMutableIndexSet *acceptableStatusCodes = [[NSMutableIndexSet alloc] initWithIndexSet:[(AFHTTPResponseSerializer *)manager.responseSerializer acceptableStatusCodes]];
[acceptableStatusCodes addIndexesInRange:NSMakeRange(300, 200)];
AFHTTPResponseSerializer *httpRespSerializer = [AFHTTPResponseSerializer serializer];
httpRespSerializer.acceptableContentTypes = acceptableContentTypes;
httpRespSerializer.acceptableStatusCodes = acceptableStatusCodes;
manager.responseSerializer = httpRespSerializer;
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:self.pluginInfo.downloadUrl];
request.timeoutInterval = 20;
self.currentLength = [self fileLengthForPath:[self tempFilePath]];
NSString *range = [NSString stringWithFormat:@"bytes=%llu-", self.currentLength];
[request setValue:range forHTTPHeaderField:@"Range"];
self.tryToUnzipWhen416Occour = NO;
__weak typeof(self) wself = self;
NSURLSessionDataTask *downloadTask = [manager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
[wself.fileHandle closeFile];
wself.fileHandle = nil;
NSHTTPURLResponse *httpResp = (NSHTTPURLResponse *)response;
if (httpResp.statusCode == 206 && error == nil)
{
// this line crash
*****NSURL *fileURL = [NSURL fileURLWithPath:[wself tempFilePath]];******
[wself performSelector:@selector(handlePackageZipFileWithFilePath:) onThread:[wself currentThread] withObject:fileURL waitUntilDone:NO];
}
else if (wself.tryToUnzipWhen416Occour && httpResp.statusCode == 416 && error.code == NSURLErrorCancelled )
{
NSURL *fileURL = [NSURL fileURLWithPath:[wself tempFilePath]];
[wself performSelector:@selector(handlePackageZipFileWithFilePath:) onThread:[wself currentThread] withObject:fileURL waitUntilDone:NO];
}
else
{
[wself performSelector:@selector(finishThread) onThread:[wself currentThread] withObject:nil waitUntilDone:NO];
}
}];
[manager setDataTaskDidReceiveResponseBlock:^NSURLSessionResponseDisposition(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLResponse *response) {
NSHTTPURLResponse *httpResp = (NSHTTPURLResponse *)response;
if (httpResp.statusCode == 206)
{
wself.fileLength = response.expectedContentLength + wself.currentLength;
NSString *filePath = [wself tempFilePath];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:filePath])
{
[fileManager createFileAtPath:filePath contents:nil attributes:nil];
}
wself.fileHandle = [NSFileHandle fileHandleForWritingAtPath:filePath];
return NSURLSessionResponseAllow;
}
else if (httpResp.statusCode == 416)
{
NSString *contentRange = [[httpResp allHeaderFields] objectForKey:@"content-range"];
if ([contentRange hasPrefix:@"bytes"])
{
NSRange slashRange = [contentRange rangeOfString:@"/"];
if (slashRange.location != NSNotFound)
{
NSString *strLength = [contentRange substringFromIndex:(slashRange.location + 1)];
long long length = strLength.longLongValue;
if (length == wself.currentLength)
{
wself.fileLength = length;
wself.tryToUnzipWhen416Occour = YES;
return NSURLSessionResponseCancel;
}
}
}
}
return NSURLSessionResponseAllow;
}];
[manager setDataTaskDidReceiveDataBlock:^(NSURLSession *session, NSURLSessionDataTask *dataTask, NSData *data) {
[wself.fileHandle seekToEndOfFile];
[wself.fileHandle writeData:data];
wself.currentLength += data.length;
}];
[downloadTask resume];
NSRunLoop *runloop = [NSRunLoop currentRunLoop];
self.port = [NSMachPort port];
[runloop addPort:self.port forMode:NSDefaultRunLoopMode];
[runloop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
}
}
- (NSString *)tempFilePath
{
NSString *fileName = [NSString stringWithFormat:@"%@_%@_%@", self.pluginInfo.pluginId, @(self.pluginInfo.pluginVersion), self.pluginInfo.pluginFileMD5];
NSString *filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:fileName];
return filePath;
}