4

UIImageView在我的UITableViewCell. 我的图像视图是 100 点乘 100 点的正方形,但UIImage我检索到的 s 并不总是具有相等的宽度和高度。

我的问题是:在加载单元格时,UIImageViews 都是 100 x 100,这很好,但是内部UIImages 被拉伸到那个大小(左图)。当我按下单元格并突出显示时,图像会突然调整到正确的比例(右图)。此外,当我进一步向下滚动到 时UITableView,所有图像也是 100x100 并被拉伸,但是当我向上滚动再次查看单元格时,它们已经突然调整大小了。不过,我不知道他们遵循的缩放比例。

在此处输入图像描述

我究竟做错了什么?我已经将UIImageViews'设置contentMode为,UIViewContentModeCenter但如您所见,它不起作用。请帮忙?我的完整代码如下。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"searchResultCell"];
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"searchResultCell"];
    }

    // Get the Ad object that will be displayed in this cell.
    Ad *ad = (Ad *)[self.searchResults objectAtIndex:indexPath.row];

    // Set up the detail text on the right.
    cell.textLabel.attributedText = ad.attributedTextDisplay;
    cell.textLabel.numberOfLines = 0;
    cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;

    // Set up the image on the left.
    NSString *thumbnailURL = ad.thumbnailURL;
    NSData *data = [FTWCache objectForKey:[MD5 hash:thumbnailURL]];

    // If the image has been previously downloaded and is stored in FTWCache.
    if (data) {
        // Then use that data instead.
        cell.imageView.image = [UIImage imageWithData:data];
    } else {
        // Assign default image before beginning background image retrieval task.
        cell.imageView.image = [UIImage imageNamed:@"image_stub_ad"];

        // Trigger background task that retrieves the actual thumbnail from the URL.
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:thumbnailURL]];

            // Proceed only with updating the table view cell if the returned NSData is not nil.
            if (imageData) {
                dispatch_sync(dispatch_get_main_queue(), ^{
                    // UPDATED: Added call to setNeedsDisplay.
                    UITableViewCell *theSameCell = [tableView cellForRowAtIndexPath:indexPath];
                    theSameCell.imageView.image = [UIImage imageWithData:imageData];
                    [theSameCell setNeedsDisplay];
                });
            }
        });
    }

    // UPDATED: Set the contentMode to UIViewContentModeScaleAspectFit instead of UIViewContentModeCenter.
    cell.imageView.contentMode = UIViewContentModeScaleAspectFit;

    return cell;
}
4

3 回答 3

0
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    ImageViewCell *cell = (ImageViewCell*)[tableView dequeueReusableCellWithIdentifier:@"identifier"];

    if (cell==nil)
    {
        cell = [[UImageViewCell alloc] init]; //or from whatever way you generate this cell.

        //Manually set this below on each time the cell is newly created.
        cell.imageView.contentMode = UIViewContentModeScaleAspectFit;
    }

    //Do the update of your imageView's image here 
    //( this is the update area when your cell is not nil 
    // and could be a reused cell.)

    cell.imageView.image = your_ui_image ;
    [cell.imageView setNeedsDisplay];

    return cell;
}
于 2013-08-01T10:12:44.567 回答
0

不是一个完整的答案,而是在异步任务中触发远程获取的“改进”:

    // Trigger background task that retrieves the actual thumbnail from the URL.
    [NSURLConnection sendAsynchronousRequest:request 
                                       queue:[NSOperationQueue mainQueue] 
                           completionHandler:^(NSURLResponse* response, 
                                               NSData* imageData, 
                                               NSError* error) {
         if (error) {
              [self handleError:error];  // connection failed
              return;
         }
         // here, at a minimum, check status code and Content-Type:
         // ... add code
         if (statusCode == 200 && contentTypeOK)  // "OK"
         {
             [FTWCache setObject:imageData forKey:[MD5 hash:thumbnailURL]];
             [tableView cellForRowAtIndexPath:indexPath].imageView.image = 
               [UIImage imageWithData:imageData];
         }
         else {
             // we didn't get an image, possibly other errors (e.g. authentication, etc.)
             NSError* err = ...;  // add code
             [self handleError:err];
             return;
         }
    }];

如果需要,此代码缺少可以取消的可能性。也没有办法阻止对同一图像启动多个请求。

上述问题与特定用户场景可能会导致应用产生无限数量的正在运行的网络请求 - 这最终会导致应用因内存问题而崩溃。为了改善这一点,我们需要利用NSURLConnection委托实现异步风格——这让我们有机会取消请求,并采取额外的措施来避免调用多个请求。

编辑:

另一个改进是执行将图像数据插入缓存以及UIImage在后台任务上创建对象,其完成处理程序更新单元格并在主线程上执行。

于 2013-08-01T10:27:47.887 回答
0

尝试这个..

// Proceed only with updating the table view cell if the returned NSData is not nil.
            if (imageData) {
                dispatch_sync(dispatch_get_main_queue(), ^{
                   UITableViewCell *imageCell = [tableView cellForRowAtIndexPath:indexPath]

                    imageCell.imageView.image = [UIImage imageWithData:imageData];
                   [imageCell setNeedsDisplay];//this is the line I added only

                    [FTWCache setObject:imageData forKey:[MD5 hash:thumbnailURL]];
                });
            }
于 2013-08-01T09:15:47.200 回答