预加载下一个(当前不可见的)单元格 UICollectionView
Preload next (currently invisible) cell UICollectionView
我正在使用 UICollectionView,目前有全屏单元格,当我滑动到下一个单元格时,图像需要一点时间才能加载到单元格中(因为它们是高分辨率的)。我已经在使用 PHCachingImageManager 来预先缓存图像,并且在我加载单元格之前它已经被缓存了,但是仅仅将图像加载到 imageView 中需要很长时间。我想知道是否有办法在到达 cellForItemAtIndexPath 之前预加载不可见的下一个单元格?
有什么想法吗?
加载已从 PHCachingImageManager 缓存的图像显然需要一些时间,这是我延迟的原因。我创建了一个测试函数,在设置当前单元格时将下一张图像(并且也会添加上一张)保存在 属性 中,我的闪烁不再存在。我将 post 清理完后的工作示例...
更新:
所以我创建了一个 _images NSMutableDictionary 来存储已经加载的图像并使用这个函数填充它
- (void)startCachingSurroundingImages:(NSInteger)index {
CGSize targetSize = PHImageManagerMaximumSize;
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
[options setNetworkAccessAllowed:YES];
[options setDeliveryMode:PHImageRequestOptionsDeliveryModeHighQualityFormat];
if (index < _imagesArray.count - 1 && ![_images objectForKey:[NSIndexPath indexPathForItem:0 inSection:index+1]]) {
NSDictionary *assetDictionary = [_imagesArray objectAtIndex:index + 1];
NSString *assetRefID = [assetDictionary objectForKey:@"asset_id"];
PHFetchResult *assetFetchResult = [PHAsset fetchAssetsWithLocalIdentifiers:@[assetRefID] options:[PHFetchOptions new]];
PHAsset *asset = [assetFetchResult firstObject];
[photoManager requestImageForAsset:asset targetSize:targetSize contentMode:PHImageContentModeAspectFit options:options resultHandler:^(UIImage *result, NSDictionary *info) {
if (result) {
[_images setObject:result forKey:[NSIndexPath indexPathForItem:0 inSection:index+1]];
}
}];
}
if (index - 1 >= 0 && ![_images objectForKey:[NSIndexPath indexPathForItem:0 inSection:index-1]]) {
NSDictionary *leftAssetDictionary = [_imagesArray objectAtIndex:index - 1];
NSString *leftAssetRefID = [leftAssetDictionary objectForKey:@"asset_id"];
PHFetchResult *leftAssetFetchResult = [PHAsset fetchAssetsWithLocalIdentifiers:@[leftAssetRefID] options:[PHFetchOptions new]];
PHAsset *leftAsset = [leftAssetFetchResult firstObject];
[photoManager requestImageForAsset:leftAsset targetSize:targetSize contentMode:PHImageContentModeAspectFit options:options resultHandler:^(UIImage *result, NSDictionary *info) {
if (result) {
[_images setObject:result forKey:[NSIndexPath indexPathForItem:0 inSection:index-1]];
}
}];
}
}
我在 cellForItemAtIndexPath 中这样调用...
[self startCachingSurroundingImages:indexPath.section];
并且仍然在 cellForItemAtIndexPath 中,我像这样加载图像...
if ([_images objectForKey:indexPath]) {
cell.imageView.image = [_images objectForKey:indexPath];
[photoCell.activityIndicator setHidden:YES];
} else {
photoCell.tag = (int)[photoManager requestImageForAsset:asset targetSize:targetSize contentMode:PHImageContentModeAspectFit options:options resultHandler:^(UIImage *result, NSDictionary *info) {
PhotoCell *photoCell = (PhotoCell *)[self.collectionView cellForItemAtIndexPath:indexPath];
if (photoCell && result) {
photoCell.imageView.image = result;
[photoCell.activityIndicator setHidden:YES];
} else {
NSLog(@"BAD IMAGE!!! %@", info);
[photoCell.activityIndicator setHidden:NO];
}
}];
}
然后在 didReceiveMemoryWarning 中我清理了一下...
- (void)didReceiveMemoryWarning {
NSArray *allKeys = [_images allKeys];
for (int i = 0; i < _images.count; i++) {
NSIndexPath *path = [allKeys objectAtIndex:i];
if (path.section != _lastIndex && path.section != _lastIndex - 1 && path.section != _lastIndex + 1) {
[_images removeObjectForKey:path];
}
}
// Though one could just as easily do this
// [_images removeAllObjects];
}
虽然不漂亮,但很管用。
我正在使用 UICollectionView,目前有全屏单元格,当我滑动到下一个单元格时,图像需要一点时间才能加载到单元格中(因为它们是高分辨率的)。我已经在使用 PHCachingImageManager 来预先缓存图像,并且在我加载单元格之前它已经被缓存了,但是仅仅将图像加载到 imageView 中需要很长时间。我想知道是否有办法在到达 cellForItemAtIndexPath 之前预加载不可见的下一个单元格?
有什么想法吗?
加载已从 PHCachingImageManager 缓存的图像显然需要一些时间,这是我延迟的原因。我创建了一个测试函数,在设置当前单元格时将下一张图像(并且也会添加上一张)保存在 属性 中,我的闪烁不再存在。我将 post 清理完后的工作示例...
更新: 所以我创建了一个 _images NSMutableDictionary 来存储已经加载的图像并使用这个函数填充它
- (void)startCachingSurroundingImages:(NSInteger)index {
CGSize targetSize = PHImageManagerMaximumSize;
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
[options setNetworkAccessAllowed:YES];
[options setDeliveryMode:PHImageRequestOptionsDeliveryModeHighQualityFormat];
if (index < _imagesArray.count - 1 && ![_images objectForKey:[NSIndexPath indexPathForItem:0 inSection:index+1]]) {
NSDictionary *assetDictionary = [_imagesArray objectAtIndex:index + 1];
NSString *assetRefID = [assetDictionary objectForKey:@"asset_id"];
PHFetchResult *assetFetchResult = [PHAsset fetchAssetsWithLocalIdentifiers:@[assetRefID] options:[PHFetchOptions new]];
PHAsset *asset = [assetFetchResult firstObject];
[photoManager requestImageForAsset:asset targetSize:targetSize contentMode:PHImageContentModeAspectFit options:options resultHandler:^(UIImage *result, NSDictionary *info) {
if (result) {
[_images setObject:result forKey:[NSIndexPath indexPathForItem:0 inSection:index+1]];
}
}];
}
if (index - 1 >= 0 && ![_images objectForKey:[NSIndexPath indexPathForItem:0 inSection:index-1]]) {
NSDictionary *leftAssetDictionary = [_imagesArray objectAtIndex:index - 1];
NSString *leftAssetRefID = [leftAssetDictionary objectForKey:@"asset_id"];
PHFetchResult *leftAssetFetchResult = [PHAsset fetchAssetsWithLocalIdentifiers:@[leftAssetRefID] options:[PHFetchOptions new]];
PHAsset *leftAsset = [leftAssetFetchResult firstObject];
[photoManager requestImageForAsset:leftAsset targetSize:targetSize contentMode:PHImageContentModeAspectFit options:options resultHandler:^(UIImage *result, NSDictionary *info) {
if (result) {
[_images setObject:result forKey:[NSIndexPath indexPathForItem:0 inSection:index-1]];
}
}];
}
}
我在 cellForItemAtIndexPath 中这样调用...
[self startCachingSurroundingImages:indexPath.section];
并且仍然在 cellForItemAtIndexPath 中,我像这样加载图像...
if ([_images objectForKey:indexPath]) {
cell.imageView.image = [_images objectForKey:indexPath];
[photoCell.activityIndicator setHidden:YES];
} else {
photoCell.tag = (int)[photoManager requestImageForAsset:asset targetSize:targetSize contentMode:PHImageContentModeAspectFit options:options resultHandler:^(UIImage *result, NSDictionary *info) {
PhotoCell *photoCell = (PhotoCell *)[self.collectionView cellForItemAtIndexPath:indexPath];
if (photoCell && result) {
photoCell.imageView.image = result;
[photoCell.activityIndicator setHidden:YES];
} else {
NSLog(@"BAD IMAGE!!! %@", info);
[photoCell.activityIndicator setHidden:NO];
}
}];
}
然后在 didReceiveMemoryWarning 中我清理了一下...
- (void)didReceiveMemoryWarning {
NSArray *allKeys = [_images allKeys];
for (int i = 0; i < _images.count; i++) {
NSIndexPath *path = [allKeys objectAtIndex:i];
if (path.section != _lastIndex && path.section != _lastIndex - 1 && path.section != _lastIndex + 1) {
[_images removeObjectForKey:path];
}
}
// Though one could just as easily do this
// [_images removeAllObjects];
}
虽然不漂亮,但很管用。