我应该如何重构此代码以从URL字符串发布UIImage? iOS版

时间:2014-10-19 22:04:28

标签: ios objective-c uiimage

这可能只是一个简单的解决方法,但我对此并不熟悉。

 NSString *barImageURLString = barDic[@"image_url"];
    NSURL *barImageURL = [NSURL URLWithString:barImageURLString];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
        NSData *imageData = [NSData dataWithContentsOfURL:barImageURL];

        dispatch_async(dispatch_get_main_queue(), ^{
            // Update the UI
            cell.barImageView.image = [UIImage imageWithData:imageData];
        });
    });

    NSString *ratingImageURLString = barDic[@"rating_img_url"];
    NSURL *ratingImageURL = [NSURL URLWithString:ratingImageURLString];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
        NSData *imageData = [NSData dataWithContentsOfURL:ratingImageURL];

        dispatch_async(dispatch_get_main_queue(), ^{
            // Update the UI
            cell.ratingImage.image = [UIImage imageWithData:imageData];
        });
    });

我不确定如何在那里使用dispatch_async。

3 个答案:

答案 0 :(得分:0)

执行POST而不仅仅是代码的重构,它将GET操作隐藏在dataWithContentsOfURL:中。这是更一般的POST代码...

NSData *data = // init this to the data that you want to post
NSString *someURLString = @"http://www.myservice.com/mypost.php";
NSURL = *url = [NSURL URLWithString:someURLString];

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
// depends on the data, but something like this to set a header...
[request setValue:@"application/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];

request.HTTPBody = data;

[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
    if (!error) {

    }
}];

这可以通过用不可变请求替换可变url请求并可选地将查询参数添加到url字符串来重构为GET。

答案 1 :(得分:0)

您的代码在理想条件下工作,但您希望进行一些错误检查以防止运行时异常。

NSString *barImageURLString = barDic[@"image_url"];
    NSURL *barImageURL = [NSURL URLWithString:barImageURLString];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
        NSData *imageData = [NSData dataWithContentsOfURL:barImageURL];
        // check for valid data
        if ( imageData ) {
            // create the UIImage first and make sure it is a valid image
            UIImage *image = [UIImage imageWithData:imageData];
            if ( image ) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    // It is possible that your tableview cell is no longer on screen, check
                    YourTableViewCell *cellBeingUpdated = (id)[tableView cellForRowAtIndexPath:indexPath];
                    if ( cellBeingUpdated ) {
                        // Update the UI
                        cellBeingUpdated.barImageView.image = image;
                    }
                });
            }
       }
    });

同样适用于您的其他图片。如果失败,您希望拥有某种默认图像。我做的是有一个默认图像,我在发出图像请求之前分配给tableview单元格。这可以防止在等待实际图像加载时出现空白图像视图。

答案 2 :(得分:0)

由于获取图像并使用它执行某些操作的逻辑大致相同,并且您不希望每次需要加载新类型的图像时重复代码,您可以创建一个函数或方法来执行重复的工作。函数的输入将是图像的URL,输出将是图像本身。由于实际的提取将是异步的,因此该功能可以作为输入一个代码块,其中包含一旦图像可用时应该做什么的指令。如果由于某种原因无法获取图像,也可以通知该块。

- (void)fetchImageFromURL:(NSURL *)imageURL completionHandler:(void(^)(UIImage *image, NSError *error))completionHandler {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
        NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
        NSError *error = ...; // do error handling if image load fails
        dispatch_async(dispatch_get_main_queue(), completionHandler(imageData, error);
    });
}

可以调用:

NSString *barImageURL = [NSURL URLWithString:barDic[@"image_url"]];
[self fetchImageFromURL:barImageURL completionHandler:^(UIImage *image, NSError *error) {
    if (error != nil) {
        // handle error
    }
    else {
        cell.barImageView.image = image;
    }
}];

虽然它似乎只是减少了几行重复​​代码,但这种设计使您的代码更加灵活和可扩展。这隐藏了实际获取图像的实现细节。也许你想用异步NSURLConnection或NSURLSession替换它。此设计允许进行此类修改而不会影响API。错误处理可以保存在一个地方。网络请求可能由于各种原因而失败,其中最重要的原因是糟糕或没有连接。您可以在-fetchImageFromURL:方法中再次为此类故障添加重试逻辑,而不会影响方法API和调用方。也许你已经建立了一些缓存,所以根本不需要去网络。同样,这种设计可以实现这种增长。

一般而言,您希望将“what”与“how”分开。 what这里是您的代码的某些部分需要的图像,但它不应该与how关联的图像被检索。