NSURL +类别与NSURLSessionDownloadTask

时间:2016-07-21 06:50:23

标签: ios objective-c cocoa-touch nsurl objective-c-category

我的NSURL有一个类别可以设置我的DataModel以便稍后访问我的模型对象。在这里,我的DataModel是我的核心数据实体(NSManagedObject)

的子类
@implementation NSURL (CustomizedObject)

static char PROPERTY_KEY;

@dynamic model;

- (void)setChunk:(DataModel *)model {
    objc_setAssociatedObject(self, &PROPERTY_KEY, model, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (DataModel *)model {
    return (DataModel *)objc_getAssociatedObject(self, &PROPERTY_KEY);
}

@end

所以,我正在通过NSURLSessionDownloadTask

下载我的数据
for (DataModel *model in models) { // Here 985 URLs are there
    if ([model.status integerValue] == 0) {
        NSURL *requestURL = [NSURL URLWithString:model.downloadSequence];
        [requestURL setModel:model];
        NSURLSessionDownloadTask *downloadTask = [self.session downloadTaskWithURL:requestURL];
        [downloadTask resume];

        [self.arrFileDownloadData addObject:downloadTask];
    }
}

而且,我在每次成功下载时都会访问DataModel

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
    self.downloadSuccessCount++;

    DownloadModel *model = downloadTask.originalRequest.URL.model;
    NSString *filePath = [model.content.filePath stringByAppendingPathComponent:[[model.streamingSequence lastPathComponent] stringByDeletingPathExtension]];

    NSError *error;
    NSFileManager *fileManager = [NSFileManager defaultManager];

    NSURL *destinationURL = [NSURL fileURLWithPath:filePath];

    if ([fileManager fileExistsAtPath:[destinationURL path]]) {
        [fileManager removeItemAtURL:destinationURL error:nil];
    }

    BOOL success = [fileManager copyItemAtURL:location toURL:destinationURL error:&error];

    if (success) {
        NSError *fetchError = nil;

        NSFetchRequest *fetch = [NSFetchRequest fetchRequestWithEntityName:ChunkCoreData];
        [fetch setPredicate:[NSPredicate predicateWithFormat: @"modelId == %@", model.modelId]];

        NSArray *isProductExist = [self.context executeFetchRequest:fetch error:&fetchError];

        if ([isProductExist count] != 0) {
            DataModel *fetchedModel = [isProductExist lastObject];
            fetchedModel.status = [NSNumber numberWithInt:2];

            // create writer MOC
            NSManagedObjectContext* _privateWriterContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
            [_privateWriterContext setPersistentStoreCoordinator:[[self managedObjectContext] persistentStoreCoordinator]];

            // create main thread MOC
            NSManagedObjectContext* _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
            _managedObjectContext.parentContext = _privateWriterContext;

            NSError *saveError = nil;
            if (![_privateWriterContext save:&saveError]) {
                NSLog(@"Couldn't save %@", saveError.localizedDescription);
            }
        }
    }
}

一切,除了有时候工作正常。我正在崩溃,

NSURL *destinationURL = [NSURL fileURLWithPath:filePath];

表示 filePath 为零。或问题在于我的NSURL类别创建?

我在这做错了什么?建议请。

1 个答案:

答案 0 :(得分:0)

我知道 NSURLSession 处理 NSURLRequest的子类;它在iOS 7中是一场灾难,在iOS 8中无法使用,在iOS 9中仍然存在很多问题。

我认为这是因为即使在进程中处理请求,对象也会被序列化为plist。我怀疑你遇到的错误与我做的相同,在这种情况下, NSURLRequest NSURL 上的关联对象可能同样存在问题。

作为替代方案,以下是一些可能更适合您的其他技术:

  • 改为使用{strong> NSURLRequest 对象上的setProperty:forKey:inRequest:property:forKey:inRequest:
  • 对于非后台会话,请将关联对象添加到任务中。
  • 创建一个字典,将URL请求对象映射到您想要的数据。

HTH。