下载多个图像并将每个图像加载到 UITableViewCell 内的 UIImageView 的最佳实践是什么?特别是,我应该在下载后调整/替换 UIImageview 的大小,还是应该调整图像的大小以适应 UIImageView。请注意,调整/替换 UIImageView 也会调整/替换 UITableViewCell。它会引起任何问题吗?
2 回答
几个想法:
下载多个图像并将每个图像加载到 a 中的最佳实践
UIImageView
是UITableViewCell
什么?
关于下载图像的最佳实践包括:
绝对利用延迟加载(根据需要而不是之前加载图像)。
异步下载图像。
确保您的下载技术将取消对不再可见的 tableview 单元格的请求。例如,如果您的网络速度较慢并且在表格视图中快速向下滚动,您不想占用您的设备下载不再可见的图像。
确保不要对服务器发出太多并发请求。在 iOS 中,当您超过 5 或 6 个并发请求时,后续请求将冻结,直到前面的请求完成。在最坏的情况下,后续请求实际上会因为超时而开始失败。
缓存您的结果。至少,将它们缓存在内存中。您可能还希望将它们缓存到持久存储(也称为“磁盘”)。
如果您要为异步操作、缓存等编写自己的代码,您可能希望使用NSOperationQueue
GCD 代替 GCD,以便我可以限制后台请求的数量并使请求可取消。您将使用NSCache
缓存图像。而且您可能会使用UITableViewCell
子类(或类别),以便您可以保存weak
对“先前”操作的引用,以便您可以取消任何不完整的先前请求。
正如您所看到的,这很重要,我建议您使用现有UIImageView
类别,例如作为SDWebImage
or的一部分提供的类别AFNetworking
。恕我直言,前者更丰富一些(例如提供磁盘缓存),但如果您正在做大量的网络工作并且想要坚持使用单一框架,AFNetworking
那么它也做得很好。
后来你问:
特别是,我应该在下载后调整/替换 UIImageview 的大小,还是应该调整图像的大小以适应 UIImageView。请注意,调整/替换 UIImageView 也会调整/替换 UITableViewCell。它会引起任何问题吗?
如果您的图像大于单元格的缩略图视图所需的大小,您有两种方法。首先,您可以使用
contentMode
ofUIViewContentModeScaleAspectFit
或UIViewContentModeScaleAspectFill
(如果您使用AspectFill
,请确保您也设置clipsToBounds
为YES
)。更好的是,您可以在下载后实际调整图像大小。这是个人意见,但我认为
UIImageView
在单元格上有一个固定大小的 UX 更好,然后在异步图像下载完成后,只需设置image
.UIImageView
您希望图像在下载时优雅地出现在您的 UI 中,但您通常不希望在用户已经在阅读那里的内容时对视图进行不和谐的重新布局。如果您的设计绝对需要重新布局单元格,那么您可以调用reloadRowsAtIndexPaths
.
在 a 中延迟加载图像的一种常见做法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;
}
}
然后在 UITableViewCell 类中重写 prepareForReuse 时:
- (void)prepareForReuse {
[super prepareForReuse];
self.myCustomImageView.imageURL = nil;
self.myCustomImageView.image = nil;
//do the rest of your prepareForReuse here:
...
}
现在,就图像的整体大小调整与图像视图的大小调整而言,您应该做的是不理会 imageView 的大小,并使用该contentMode
属性来处理结果图像的不同大小。您可能的值是:
UIViewContentModeScaleToFill,
UIViewContentModeScaleAspectFit,
UIViewContentModeScaleAspectFill,
UIViewContentModeRedraw,
UIViewContentModeCenter,
UIViewContentModeTop,
UIViewContentModeBottom,
UIViewContentModeLeft,
UIViewContentModeRight,
UIViewContentModeTopLeft,
UIViewContentModeTopRight,
UIViewContentModeBottomLeft,
UIViewContentModeBottomRight,
每个都有各自的结果 - 您可能想要使用UIViewContentModeScaleAspectFit
它,因为这将重新调整图像大小以适合 imageView,而不会扭曲它 - 这可能会在 imageView 的大小或顶部/底部留下空白边距。Aspect fill 会做类似的事情,只是它会将图像调整为足够大以填充整个 imageView,并且可能会切断图像的侧面或顶部/底部。Scale to fill 只会拉伸图像以填充 imageView。