平滑滚动500张图像

时间:2013-08-30 17:31:27

标签: ios objective-c uicollectionview

SUPER EDIT:

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

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

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

UICollectionview

- (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到全视图控制器,显示全分辨率照片。如何先加载缩略图然后再加载完整尺寸的图像。

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

精制编辑:


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

2 个答案:

答案 0 :(得分:6)

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

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

缓存的工作原理如下:

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

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

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

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

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

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

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

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

答案 1 :(得分: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