在UITableView中延迟加载多个图像

时间:2012-07-20 16:09:51

标签: ios uitableview uiimageview

下载多个图像并在UITmageView内部的UIImageView中加载每个图像的最佳做法是什么?特别是,我应该在下载后调整大小/替换UIImageview,还是应该调整图像大小以适应UIImageView。请注意,调整大小/替换UIImageView也会调整大小/替换UITableViewCell。它会引起任何问题吗?

2 个答案:

答案 0 :(得分:3)

有几点想法:

  

下载多张图片并在UIImageView内的UITableViewCell中加载每张图片的最佳做法是什么?

有关下载图像的最佳做法包括:

  1. 绝对可以利用延迟加载(根据需要加载图像而不是之前加载图像)。

  2. 异步下载图片。

  3. 确保您的下载技术将取消对不再可见的tableview单元格的请求。例如,如果您使用的是慢速网络并在桌面视图中快速向下滚动,则不希望将设备下载为不再可见的图像。

  4. 确保您没有为服务器发出太多并发请求。在iOS中,当您超过5或6个并发请求时,后续请求将冻结,直到前一个请求完成。在最坏的情况下,后续请求实际上会在超时时开始失败。

  5. 缓存结果。至少,将它们缓存在内存中。您可能还想将它们缓存到持久存储(也就是“磁盘”)。

  6. 如果您要为异步操作,缓存等编写自己的代码,可能需要使用NSOperationQueue而不是GCD,这样我就可以约束number of background requests并发出请求{{ 3}}。您可以使用cancelable来缓存图像。并且您可能使用UITableViewCell子类(或类别),以便您可以保存weak对“之前”操作的引用,以便您可以取消任何不完整的先前请求。

    正如您所看到的,这非常重要,我建议您使用现有的UIImageView类别,例如NSCacheSDWebImage中提供的类别。恕我直言,前者更富有(例如提供磁盘缓存),但如果你做了很多网络工作并且想要坚持使用单一框架,AFNetworking也做得很好。

    后来你问:

      

    特别是,我应该在下载后调整大小/替换UIImageview,还是应该调整图像大小以适应UIImageView。请注意,调整大小/替换UIImageView也会调整大小/替换UITableViewCell。它会引起任何问题吗?

    1. 如果您的图像大于单元格缩略图视图所需的图像,则有两种方法。首先,您可以使用contentMode AFNetworking(如果您使用AspectFill,请确保同时将clipsToBounds设置为YES)。更好的是,您下载后实际上可以UIViewContentModeScaleAspectFit or UIViewContentModeScaleAspectFill

    2. 这是个人意见,但我认为在单元格上拥有UIImageView固定大小是一个更好的用户体验,然后在完成异步图像下载时,只需设置image属性UIImageView的。{您希望图像在下载时优雅地显示在UI中,但是当用户已经在阅读其中的内容时,您通常不希望对视图进行重新布局。如果您的设计绝对需要重新布局单元格,那么您只需拨打resize the image

答案 1 :(得分:0)

UITableViewCell中延迟加载图片的一种常见做法是使用通知回调让UITableViewCell知道何时收到图片。

从本质上讲,您需要创建一个UIImageView的子类,该子类具有imageURL字段,当更改时,会触发对图像的请求,并使用该字段而不是标准UIImageView

UIImageView子类的接口:

@property (nonatomic, copy) NSString *imageURL;

UIImageView子类的实现:

//synthesize property
@synthesize imageURL = _imageURL;

- (void)setImageURL:(NSString *)imageURL {
    if(_imageURL)
        [[NSNotificationCenter defaultCenter] removeObserver:self name:_imageURL object:nil];
    _imageURL = [imageURL copy];
    //if imageURL is valid...
    if(_imageURL.length) {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveImage:) name:_imageURL object:nil];
        //fire off some asynchronous image fetch
        //when the image fetch completes, sent off a notification using the imageURL as the notification name
        //It's up to you to create the implementation for this yourself
        ... [MyImageManager fetchImage:_imageURL notificationName:_imageURL]; 
    }
}

- (void)didReceiveImage:(NSNotification*)notification
{
    //handle your received image here
    if([notification.object isKindOfClass:[UIImage class]])
    {
        self.myCustomImageView.image = notification.object;
    }
}

然后在覆盖prepareForReuse时在UITableViewCell类中:

- (void)prepareForReuse {
    [super prepareForReuse];
    self.myCustomImageView.imageURL = nil;
    self.myCustomImageView.image = nil;
    //do the rest of your prepareForReuse here:
    ...
}

现在,就整个图像重新调整尺寸和调整图像视图的大小而言,你应该做的是单独保留imageView的大小,并使用contentMode属性来处理不同的大小。结果图像。您的possible values是:

UIViewContentModeScaleToFill,
UIViewContentModeScaleAspectFit,
UIViewContentModeScaleAspectFill,
UIViewContentModeRedraw,
UIViewContentModeCenter,
UIViewContentModeTop,
UIViewContentModeBottom,
UIViewContentModeLeft,
UIViewContentModeRight,
UIViewContentModeTopLeft,
UIViewContentModeTopRight,
UIViewContentModeBottomLeft,
UIViewContentModeBottomRight,

每个都有各自的结果 - 您可能希望使用UIViewContentModeScaleAspectFit,因为这会重新调整图像大小以适应imageView,而不会扭曲它 - 这可能会留下空白边距或大小/ viewView的底部。 Aspect填充将执行类似的操作,只是它会将图像调整为足够大以填充整个imageView,并且可能会切掉图像的边或顶部/底部。缩放到填充只会拉伸图像以填充图像。