Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 在CellForRowatineXpath中使用dispatch\u async加载映像_Ios_Objective C_Uitableview_Nsdata_Dispatch Async - Fatal编程技术网

Ios 在CellForRowatineXpath中使用dispatch\u async加载映像

Ios 在CellForRowatineXpath中使用dispatch\u async加载映像,ios,objective-c,uitableview,nsdata,dispatch-async,Ios,Objective C,Uitableview,Nsdata,Dispatch Async,我正在尝试从url加载图像 下面是我的代码 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = nil; cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:@""]; if (

我正在尝试从url加载图像

下面是我的代码

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

  UITableViewCell *cell = nil;

    cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:@""];

    if (cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                      reuseIdentifier:nil];
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    }

    dispatch_async (dispatch_get_main_queue(), ^{

        NSData * storeImageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:productImageArray[indexPath.row]]];

        self.productImage.image = [UIImage imageWithData:storeImageData];
        });

            [cell.contentView addSubview:self.productImage];

return cell;
}
问题是,

  • UI冻结,直到加载图像
  • 只有最后一个单元格正在加载图像,但其余单元格未加载图像

  • 我怎样才能解决这个问题呢?

    试试
    NSURLSessionTask

    NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (data) {
            UIImage *image = [UIImage imageWithData:data];
            if (image) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    UITableViewCell * cell = (id)[tableView cellForRowAtIndexPath:indexPath];
                    if (cell)
                        cell. productImage.image = image;
                });
            }
        }
    }];
    [task resume];
    

    您正在主UI线程上同步下载图像,导致屏幕冻结

    请按照以下文章解决此问题:

    还要回答你的第二点:

    您似乎在使用CellForRowatineXpath方法之外实例化的单个imageView,然后尝试将其添加到每个单元格中,这将导致图像从上一个单元格中删除,并添加到当前单元格中


    因为一个视图只能有一个超级视图,并且一旦您尝试在其他视图中添加子视图,它将从当前超级视图中删除。您可以使用GCD在后台线程中加载图像,如下所示:

      //get a dispatch queue
    
        dispatch_queue_t concurrentQueue =  dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
        //this will start the image loading in bg
    
        dispatch_async(concurrentQueue, ^{        
            NSData *image = [[NSData alloc] initWithContentsOfURL:imageURL];
    
            //this will set the image when loading is finished
    
            dispatch_async(dispatch_get_main_queue(), ^{
                imageView.image = [UIImage imageWithData:image];
            });
        });
    
    但解决这些问题的最简单的修复方法是使用UIImageView类别,如随或提供的。如果您愿意,您可以编写自己的代码来处理上述问题,但这需要大量的工作,而且上面的UIImageView类别已经为您完成了这项工作。

    试试这个:

        UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
        cell.imageView.image = image;  
    
    或者有时我要做的是更新模型,然后在特定的位置重新加载单元格:

      myModel.image = downloadedThumbImage;
      [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                                      withRowAnimation:UITableViewRowAnimationNone];  
    
    
      - (UITableViewCell *)tableView:(UITableView *)tableView    cellForRowAtIndexPath:(NSIndexPath *)indexPath
      {
        static NSString *CellIdentifier = @"top50places";
        UITableViewCell *cell = [tableView   dequeueReusableCellWithIdentifier:CellIdentifier];
    
       //getting the selected row image 
      NSDictionary* currentImageDictionary=[self.topfifty objectAtIndex:indexPath.row];//topFifty is an array of image dictionaries
    
       UIImage *currentImage = [currentImageDictionary objectForKey:@"image"];
    
      if (currentImage) { 
          // we already fetched the image, so we just set it to the cell's image view
         cell.imageView.image = currentImage;
      }
      else {
           // we don't have the image, so we need to fetch it from the server  
    
       // In the meantime, we can set some place holder image
       UIImage *palceholderImage = [UIImage imageNamed:@"placeholder.png"];
       cell.imageView.image = palceholderImage;
    
      // set the placeholder as the current image to your model, so you won't 
      // download the image multiple times (can happen if you reload this cell while 
      // download is in progress)
      [currentImageDictionary setObject:palceholderImage forKey:@"image"];
    
      // then download the image
      // creating the download queue 
      dispatch_queue_t downloadQueue=dispatch_queue_create("thumbnailImage", NULL);
    
      dispatch_async(downloadQueue, ^{
         UIImage *downloadedThumbImage=[self getImage:currentImageDictionary] ;
    
         //Need to go back to the main thread since this is UI related
         dispatch_async(dispatch_get_main_queue(), ^{
                // store the downloaded image in your model
                [currentImageDictionary setObject:image forKey:@"image"];
    
                // update UI
                UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
                cell.imageView.image = image;    
         });
      });
      dispatch_release(downloadQueue);
    
       }
    
     return cell;
     }
    

    我觉得这是异步下载图像的最佳方法。对于这个任务,我将始终使用下面的方法

    单元格中,按行索引路径:

    并添加此方法


    使用此功能,即使我们在下载图像时也可以更好地了解是否存在任何问题。

    @MGR,您可以使用Dispatch async,但有一个库,一个优秀的库。它将处理图像下载,并有一个方法在imageview.public中加载图像
    func hnk_setImageFromURL(URL:NSURL,占位符:UIImage?=默认,格式:Haneke.format?=默认,失败:((NSError?->())?=默认,成功:((UIImage)->())?=默认)

    它还具有缓存功能。因此,您可以在
    cellForRow
    中简单地实现此功能。就这样,一切都由哈内克来处理

    *请使用此框架*


    这带来了比Hanekeswift更好的性能和定制,请参见Apple。由于未捕获的异常“NSInvalidArgumentException”,它会引发终止应用程序,原因:'-[\u NSCFString absoluteURL]:无法识别的选择器发送到实例0x155886fd0'@karupumgr检查您的url@KaruppuMGR如果您有更多的web服务,我建议您使用网络,直到只加载最后一张图像为止。此库也可用于objective c。使用cocoapods将此库下载到您的项目中。然后在cellForRow方法中使用这样的方法。就这样。[imageView hnk_setImageFromURL:url];还有其他选择吗?您可以在项目中手动拖放该库。如果您不使用cocoapodsIm不使用cocoa Pods,请在项目中删除该库。这里的一个问题是,在主线程上使用异步任务不会阻塞UI吗?
     NSURL *imgURL = [[NSURL URLWithString:productImageArray[indexPath.row]];
     [self downloadImageWithURL:imgURL
                completionBlock:^(BOOL succeeded, UIImage *image) {
                              self.productImage.image=image;
         }];
    
    - (void)downloadImageWithURL:(NSURL *)url completionBlock:(void (^)(BOOL succeeded, UIImage *image))completionBlock
    {
         NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
         [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue]
              completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
                 if ( !error )
                  {
                    data = [NSData dataWithContentsOfURL:url];
                    UIImage *image = [[UIImage alloc] initWithData:data];
                    completionBlock(YES,image);
                  } else{
                     NSLog(@"Error in downloading image:%@",url);
                     completionBlock(NO,nil);
                  }
               }];
    }