gpt4 book ai didi

ios - dataWithContentsOfURL 与 downloadTaskWithURL

转载 作者:行者123 更新时间:2023-12-01 16:41:14 25 4
gpt4 key购买 nike

当我使用从另一个 Web 服务检索的 url 获取图像数据,并且我需要更新模型对象时,我总是在更新相应的 View 时遇到问题。本质上,这是问题所在:

  • 调用 Web 服务 A
  • 检索图像 URL - 第一次调用返回 block
  • 使用图像 URL
  • 调用 Web 服务
  • 检索图像数据
  • 使用图像数据更新模型对象
  • 根据模型对象更新 View 对象缩略图(例如:uicollectionviewcell 或 uitableviewcell)(此处出现问题)

  • 我之前在 AFNetworking 和相应的 NSURLSession 中使用过这种方法。但是,问题是,在我更新了模型对象之后,我需要在缩略图出现之前滚动 Collection View 或表格 View 。否则,在第一次加载时,图像保持空白。

    请参阅下面的代码以获取此方法的示例:
    - (void)searchFlickrForTerm:(NSString *) term completionBlock:(FlickrSearchCompletionBlock) completionBlock
    {
    NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
    _session = [NSURLSession sessionWithConfiguration:config
    delegate:self
    delegateQueue:nil];

    NSString *requestString = [Flickr flickrSearchURLForSearchTerm:term];
    NSURL *url = [NSURL URLWithString:requestString];
    NSURLRequest *req = [NSURLRequest requestWithURL:url];

    NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:req completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){
    if (error != nil) {
    completionBlock(term,nil,error);
    }
    else{
    NSDictionary *searchResultsDict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
    //This is the segment where we parse the Flickr data
    NSString * status = searchResultsDict[@"stat"];
    if ([status isEqualToString:@"fail"]) {
    NSError * error = [[NSError alloc] initWithDomain:@"FlickrSearch" code:0 userInfo:@{NSLocalizedFailureReasonErrorKey: searchResultsDict[@"message"]}];
    completionBlock(term, nil, error);
    } else {

    NSArray *objPhotos = searchResultsDict[@"photos"][@"photo"];
    NSMutableArray *flickrPhotos = [@[] mutableCopy];
    for(NSMutableDictionary *objPhoto in objPhotos)
    {
    //Good Idea to parse in the web service call itself. The structure might be different
    //If parse in the model class, can be very complicated if the structure is different
    FlickrPhoto *photo = [[FlickrPhoto alloc] init];
    photo.farm = [objPhoto[@"farm"] intValue];
    photo.server = [objPhoto[@"server"] intValue];
    photo.secret = objPhoto[@"secret"];
    photo.photoID = [objPhoto[@"id"] longLongValue];

    NSString *searchURL = [Flickr flickrPhotoURLForFlickrPhoto:photo size:@"m"];
    //Call to retrieve image data
    NSURLSessionDownloadTask *getImageTask = [_session downloadTaskWithURL:[NSURL URLWithString:searchURL] completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error){
    UIImage *downloadImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:location]];
    photo.thumbnail = downloadImage;
    }];

    [getImageTask resume];
    [flickrPhotos addObject:photo];
    }

    completionBlock(term,flickrPhotos,nil);
    }
    //End parse of Flickr Data
    }
    }];

    [dataTask resume];
    //End
    }

    在上面的代码段中,我解析完 FlickrPhoto 模型对象后,使用 NSURLDownloadTask 调用图片的 url。这是有问题的代码段。

    方法一:
    NSURLSessionDownloadTask *getImageTask = [_session downloadTaskWithURL:[NSURL URLWithString:searchURL] completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error){
    UIImage *downloadImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:location]];
    photo.thumbnail = downloadImage;
    }];

    [getImageTask resume];

    但是,如前所述,即使在我更新了 photo.thumbnail 属性之后,在我将 imageView 设置为从缩略图属性读取的 uicollectionview 中,除非滚动,否则图像不会显示在我的 Collection View 中。

    然而,有趣的是,我没有使用 NSURLDownloadTask,而是只使用 dataWithContentsOfURL,而无需滚动 Collection View 即可显示图像。

    方法 B:
    NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:searchURL]
    options:0
    error:&error];
    UIImage *image = [UIImage imageWithData:imageData];
    photo.thumbnail = image;

    我不知道为什么会这样。我还通过抓取 View Controller 中的主线程来重新加载 Collection View 数据。
    dispatch_async(dispatch_get_main_queue(), ^{
    [self.collectionView reloadData];
    });

    对于这篇冗长的帖子,我真的很抱歉,但如果有人能就此提出建议,我将不胜感激。我已经阅读了文档,但我还没有找到这个令人费解的问题的有意义的答案。

    最佳答案

    好的,在仔细研究了 Apple 的文档之后,我想我知道了这个问题。

    本质上,在我的方法 A 中,downloadTaskWithURL 将分拆另一个后台线程。因此,即使我已经更新了模型对象,除非我再次捕获主线程并刷新 View ,否则 View 不会用新信息更新。

    但是,在方法 B 中,dataWithContentsOfURL 同步运行。因此,根本不存在后台线程的问题。

    来自苹果文档:

    dataWithContentsOfURL: Returns a data object containing the data from the location specified by a given URL.

    Discussion This method is ideal for converting data:// URLs to NSData objects, and can also be used for reading short files synchronously. If you need to read potentially large files, use inputStreamWithURL: to open a stream, then read the file a piece at a time.



    如果我的理解有误,请随时纠正我。如果我认为该解决方案更好地回答了我的疑问,我很乐意将我接受的答案更改为您的答案。

    关于ios - dataWithContentsOfURL 与 downloadTaskWithURL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24206568/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com