AFNetworking for Image Downloads,无响应的用户界面

时间:2012-04-09 18:47:03

标签: ios multithreading core-data thread-safety afnetworking

我正在使用AFNetworking从URL中提取图像,调整大小,存储到磁盘并在Core Data中记录路径,然后加载到表视图和存储。当代码执行时,它会冻结我的UI。我不确定这是导致我麻烦的下载还是操作。

我正在使用的代码位于

之下
- (void)getPhoto:(NSInteger)type forManagedObject:(MyManagedObject*)object {

    // download the photo
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:object.photoUrl]];
    AFImageRequestOperation *operation = [AFImageRequestOperation imageRequestOperationWithRequest:request success:^(UIImage *image) {


        // MyManagedObject has a custom setters (setPhoto:,setThumb:) that save the
        // images to disk and store the file path in the database 
        object.photo = image;
        object.thumb = [image imageByScalingAndCroppingForSize:CGSizeMake(PhotoBlockCellButtonWidth, PhotoBlockCellButtonHeight)];

        NSError *nerror;
        if (![[DataStore sharedDataStore].managedObjectContext save:&nerror]) {
            NSLog(@"Whoops, couldn't save: %@", [nerror localizedDescription]);
            return;
        }

        // notify the table view to reload the table
        [[NSNotificationCenter defaultCenter] postNotificationName:@"ReloadTableView" object:nil];

    }];
    [operation start];
}

这是一个与我的托管对象

中的setter相关的示例代码
- (NSString*)uniquePath{

    // prepare the directory string
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];

    // acquire a list of all files within the directory and loop creating a unique file name
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSArray *existingFiles = [fileManager contentsOfDirectoryAtPath:documentsDirectory error:nil];
    NSString *uniquePath;
    do {
        CFUUIDRef newUniqueId = CFUUIDCreate(kCFAllocatorDefault);
        CFStringRef newUniqueIdString = CFUUIDCreateString(kCFAllocatorDefault, newUniqueId);

        uniquePath = [[documentsDirectory stringByAppendingPathComponent:(__bridge NSString *)newUniqueIdString] stringByAppendingPathExtension:@"png"];

        CFRelease(newUniqueId);
        CFRelease(newUniqueIdString);
    } while ([existingFiles containsObject:uniquePath]);

    return uniquePath;
}

- (NSString*)saveImage:(UIImage*)image{
    NSString *path = [self uniquePath];
    NSData *data = UIImagePNGRepresentation(image);
    [data writeToFile:path atomically:YES];
    return [NSString stringWithFormat:@"file://%@",path];
}

- (void) setPhoto:(UIImage *)image {
    self.photoUrl = [self saveImage:image];
}

我想把它推到后台线程,但我不确定AFNetworking,Core Data和Messaging在线程安全方面的含义是什么。有什么想法吗?

2 个答案:

答案 0 :(得分:4)

AFAIK,您执行请求的方式不正确:

[operation start];

您应该将操作添加到NSOperationQueue

    NSOperationQueue* operationQueue = [[NSOperationQueue alloc] init];
    [operationQueue addOperation:operation];

(你应该正确地对队列进行内存管理)。

通过这样做,您的请求将以异步方式执行,它不会阻止UI,您也不需要处理多线程。

答案 1 :(得分:3)

根据Matt的建议,我通过重新调整我的调用来改进UI。

- (void)getPhoto:(NSInteger)type forManagedObject:(MyManagedObject*)object {

    // download the photo
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:object.photoUrl]];
    AFImageRequestOperation *operation = [AFImageRequestOperation 
        imageRequestOperationWithRequest:request 
        imageProcessingBlock:^UIImage *(UIImage *image) {
            return [image imageByScalingAndCroppingForSize:CGSizeMake(PhotoBlockCellButtonWidth, PhotoBlockCellButtonHeight)];
        } 
        cacheName:nil 
        success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {

            // MyManagedObject has a custom setters (setPhoto:,setThumb:) that save the
            // images to disk and store the file path in the database 
            object.photo = image;
            object.thumb = image;

            NSError *nerror;
            if (![[DataStore sharedDataStore].managedObjectContext save:&nerror]) {
                NSLog(@"Whoops, couldn't save: %@", [nerror localizedDescription]);
                return;
            }

            // notify the table view to reload the table
            [[NSNotificationCenter defaultCenter] postNotificationName:@"ReloadTableView" object:nil];                                                                 
        } 
        failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
            NSLog(@"Error getting photo");
        }];
    [operation start];
}