下载多个图像并在UITmageView内部的UIImageView中加载每个图像的最佳做法是什么?特别是,我应该在下载后调整大小/替换UIImageview,还是应该调整图像大小以适应UIImageView。请注意,调整大小/替换UIImageView也会调整大小/替换UITableViewCell。它会引起任何问题吗?
答案 0 :(得分:3)
有几点想法:
下载多张图片并在
UIImageView
内的UITableViewCell
中加载每张图片的最佳做法是什么?
有关下载图像的最佳做法包括:
绝对可以利用延迟加载(根据需要加载图像而不是之前加载图像)。
异步下载图片。
确保您的下载技术将取消对不再可见的tableview单元格的请求。例如,如果您使用的是慢速网络并在桌面视图中快速向下滚动,则不希望将设备下载为不再可见的图像。
确保您没有为服务器发出太多并发请求。在iOS中,当您超过5或6个并发请求时,后续请求将冻结,直到前一个请求完成。在最坏的情况下,后续请求实际上会在超时时开始失败。
缓存结果。至少,将它们缓存在内存中。您可能还想将它们缓存到持久存储(也就是“磁盘”)。
如果您要为异步操作,缓存等编写自己的代码,可能需要使用NSOperationQueue
而不是GCD,这样我就可以约束number of background requests并发出请求{{ 3}}。您可以使用cancelable来缓存图像。并且您可能使用UITableViewCell
子类(或类别),以便您可以保存weak
对“之前”操作的引用,以便您可以取消任何不完整的先前请求。
正如您所看到的,这非常重要,我建议您使用现有的UIImageView
类别,例如NSCache
或SDWebImage
中提供的类别。恕我直言,前者更富有(例如提供磁盘缓存),但如果你做了很多网络工作并且想要坚持使用单一框架,AFNetworking
也做得很好。
后来你问:
特别是,我应该在下载后调整大小/替换UIImageview,还是应该调整图像大小以适应UIImageView。请注意,调整大小/替换UIImageView也会调整大小/替换UITableViewCell。它会引起任何问题吗?
如果您的图像大于单元格缩略图视图所需的图像,则有两种方法。首先,您可以使用contentMode
AFNetworking
(如果您使用AspectFill
,请确保同时将clipsToBounds
设置为YES
)。更好的是,您下载后实际上可以UIViewContentModeScaleAspectFit
or UIViewContentModeScaleAspectFill
。
这是个人意见,但我认为在单元格上拥有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,并且可能会切掉图像的边或顶部/底部。缩放到填充只会拉伸图像以填充图像。