5

超级编辑:

好吧,经过几次不同的修改,我有一个更明确的问题。基本上我正在努力使用 NSCache。我有一个集合视图,如下所示,我希望能够最大限度地减少图像的滚动延迟,我大部分时间都在这样做。困难的部分是移动到全尺寸图像。这是另一种观点,我希望过渡到全尺寸照片,就像 Apple 使用他们的照片应用程序所做的那样。

似乎苹果正在缓存图像并以不同的方式访问它们。我发现我需要加载原始缩略图,然后在下载全尺寸图像时我可以替换它。但我不知道该怎么做。

到目前为止,我所拥有的是:

UICollection 视图

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    self.myCache = [[NSCache alloc] init];

}

//Reusable cell structure
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {

    //cell
    CoverPhotoCell *cell = [cv dequeueReusableCellWithReuseIdentifier:@"CoverImgCell" forIndexPath:indexPath];
    cell.backgroundColor = [UIColor blackColor];
    cell.clipsToBounds = YES;
    cell.opaque = YES;
    cell.layer.shouldRasterize = YES;
    cell.layer.rasterizationScale = [UIScreen mainScreen].scale;

    Media *object = [[Media alloc] init];
    object = [self.photoListArray objectAtIndex:indexPath.item];

    //Remove old cell
    for (UIView *subview in [cell subviews]){
        if (subview.tag != 0 )
        {
            [subview removeFromSuperview];
        }
    }

    //UIImage
    UIImage *thumbImg = [_myCache objectForKey:object.url];

    if (thumbImg) {

        cell.imageView.image = thumbImg;
    }
    else {

        cell.imageView.image = nil;

        UIImage *thumbImg = [[UIImage alloc] initWithCGImage:[object.asset aspectRatioThumbnail]];

        dispatch_async(dispatch_get_main_queue(), ^{
            cell.imageView.image = thumbImg;
        });

        [_myCache setObject:thumbImg forKey:object.url];

    }

    //thumbnail
    cell.imageView.tag = indexPath.row + 1;

    cell.imageView.layer.borderWidth = 5;
    cell.imageView.layer.borderColor = [UIColor whiteColor].CGColor;
    cell.imageView.contentMode = UIViewContentModeScaleAspectFit;

    cell.imageView.frame = CGRectMake(0, 0, 125, 125);

    return cell;
}

//User taps image
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@"PhotoSegue"]) {
        DetailPageController *controller = segue.destinationViewController;

        NSIndexPath *selectedIndex = [self.collectionView indexPathsForSelectedItems][0];

        controller.initialIndex = (NSUInteger)selectedIndex.item;

        controller.photos = self.photoListArray;

    }
}

这就是我的 NSCache 代码,然后我使用 segue 到显示全分辨率照片的全视图控制器。如何先加载缩略图,然后再加载全尺寸图像。

还有关于苹果如何如此快速地加载其图像的任何想法?他们是否使用不同的缓存方式?或者我做错了什么。

精致编辑:


有人可以发布或至少将我指向一些示例代码,当用户快速滚动时我会显示缩略图并在他们放慢速度时加载实际图像,类似于我猜苹果电影预告片应用程序。

4

2 回答 2

6

一个完整的代码答案对于 SO 来说太过分了。所以我尝试描述基础知识:

您应该创建自己的图像缓存。使用页面滚动视图,最多可以看到两个图像。在启用分页的滚动视图中查看照片时,图像缓存必须至少保存三个完整大小的图像。

缓存的工作原理如下:

假设您有一个图像列表,可以通过与“相册查看器”滚动视图中的位置相对应的索引来访问该列表。

当前索引,(异步)将图像加载到 index-1、index 和 index+1 的缓存中,除非该图像已存在于缓存中或索引超出范围。

当用户开始滚动时,下一个图像将变得可见。

当用户向前滚动并滚动了半页时,当前索引将增加一。此时,可以看到两个图像 - 每个图像的一半。现在,当索引更改时,您将图像放在当前索引 2 处,并在当前索引 + 1 处加载下一个图像。

当用户向后滚动时,索引会减一。你抛出 at index+2 并为当前 index-1 加载相应的图像。

您可以通过添加与上述完全相同的缩略图视图缓存来改进该方案,但使用范围更广,例如提前加载 20 张图像。当完整大小的图像尚未加载时,使用拇指图像作为“占位符”(注意:一切都应是异步的)。

如果用户“快速”滚动,则不要加载全尺寸图像,只需等待速度降低到一定量即可。您可以通过一些努力来确定滚动的速度。

如果用户滚动得非常快,那么当它应该显示时,即使是拇指图像也不可用。然后,求助于静态占位符图像。(还要注意不要用拇指图像覆盖全尺寸图像)。

于 2013-08-30T18:15:47.973 回答
1

我会用AFNetworking加载图像。

您可以使用以下

[imageView setImageWithURL:[NSURL URLWithString:@"http://i.imgur.com/r4uwx.jpg"] placeholderImage:[UIImage imageNamed:@"placeholder-avatar"]];

您可以将占位符加载为缩略图,加载后它将被其他图像替换。

http://cocoadocs.org/docsets/AFNetworking/1.3.1/Categories/UIImageView+AFNetworking.html

于 2013-09-19T14:07:07.113 回答