繁体   English   中英

使用UIImage和下载的图像进行缓存

[英]Caching with UIImage and downloaded images

我有一个类方法,它用完成块来获取图像。 将该获取的UIImage与相关密钥一起添加到NSCache中。 但是,这似乎按预期工作,但是在使用UIImageimageWithData:方法获取图像的方法中,我发现它不会缓存其数据,只有imageNamed:可以。

因此,我得到内存警告是可以理解的,如何确保不再需要用UIImageimageWithData:方法加载的图像从内存中删除?

编辑

这是下载图像的方法的代码。

- (void)imageForFootageSize:(FootageSize)footageSize withCompletionHandler:(void (^)(UIImage *image))completionBlock
{
    if (completionBlock) {
        __block UIImage *image;

        //  Try getting local image from disk.
        //
        __block NSURL *imageURL = [self localURLForFootageSize:footageSize];

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            image = [UIImage imageWithData:[NSData dataWithContentsOfURL:imageURL]];

            dispatch_async(dispatch_get_main_queue(), ^{
                if (image) {
                    completionBlock(image);
                } else {
                    //
                    //  Otherwise try getting remote image.
                    //
                    imageURL = [self remoteURLForFootageSize:footageSize];

                    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                        NSData *imageData = [NSData dataWithContentsOfURL:imageURL];

                        dispatch_async(dispatch_get_main_queue(), ^{
                            image = [UIImage imageWithData:imageData];

                            if (image) {
                                //
                                //  Save remote image to disk
                                //
                                NSURL *photoDirectoryURL = [Footage localURLForDirectory];

                                //      Create the folder(s) where the photos are stored.
                                //
                                [[NSFileManager defaultManager] createDirectoryAtPath:[photoDirectoryURL path] withIntermediateDirectories:YES attributes:nil error:nil];

                                //      Save photo
                                //
                                NSString *localPath = [[self localURLForFootageSize:footageSize] path];
                                [imageData writeToFile:localPath atomically:YES];
                            }

                            completionBlock(image);
                        });
                    });
                }
            });
        });
    }
}

编辑2

使用上述类方法的方法在completionHandler中获取并处理UIImage

UICollectionViewCell子类中的方法。

- (void)setPhoto:(Photo *)photo withImage:(UIImage *)image
{
    [self setBackgroundColor:[UIColor blackColor]];
    [self.imageView setBackgroundColor:[UIColor clearColor]];

    if (photo && !image) {
        [photo imageForFootageSize:[Footage footageSizeThatBestFitsRect:self.bounds]
             withCompletionHandler:^(UIImage *image) {
                 if ([self.delegate respondsToSelector:@selector(galleryPhotoCollectionViewCell:didLoadImage:)]) {
                     [self.delegate galleryPhotoCollectionViewCell:self didLoadImage:image];
                 }

                 image = nil;
             }];
    }

    [self.imageView setImage:image];

    BOOL isPhotoAvailable = (BOOL)(image);

    [self.imageView setHidden:!isPhotoAvailable];
    [self.activityIndicatorView setHidden:isPhotoAvailable];
}

UICollectionView数据源委托中的方法

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    DIGalleryPhotoCollectionViewCell *photoCell = [collectionView dequeueReusableCellWithReuseIdentifier:photoCellIdentifier forIndexPath:indexPath];

    [photoCell setDelegate:self];

    Footage *footage = [self footageForIndexPath:indexPath];
    Photo *photo = ([footage isKindOfClass:[Photo class]]) ? (Photo *)footage : nil;

    if (photo) {
        //
        //  Photo
        //
        [photoCell setPhoto:photo withImage:[self.galleryCache objectForKey:photo.footageID]];
    }

    return photoCell;
}

以下是其他相关方法:

- (void)galleryPhotoCollectionViewCell:(DIGalleryPhotoCollectionViewCell *)cell didLoadImage:(UIImage *)image
{
    NSIndexPath *indexPath = [self.galleryCollectionView indexPathForCell:cell];

    Footage *footage = [self footageForIndexPath:indexPath];

    if ([footage isKindOfClass:[Footage class]]) {
        Photo *photo = (Photo *)footage;

        UIImage *cachedImage = [self.galleryCache objectForKey:photo.footageID];

        if (!cachedImage) {
            cachedImage = image;

            [self.galleryCache setObject:image forKey:photo.footageID];
        }

        [cell setPhoto:photo withImage:image];
    }
}

还有我的NSCache属性galleryCache getter方法

- (NSCache *)galleryCache
{
    if (!_galleryCache) {
        _galleryCache = [[NSCache alloc] init];
    }

    return _galleryCache;
}

与其发布自己的图像下载和缓存解决方案,不如使用SDWebImage更好。 然后,您不必担心下载,缓存或其他任何事情。 SDWebImage还使用磁盘缓存,因此您不必担心释放内存。

SDWebImageManager *manager = [SDWebImageManager sharedManager];
[manager downloadWithURL:imageURL options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize)
    {
        // progression tracking code
    } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished)
    {
        if (image)
        {
            // do something with image
        }
    }];

我不确定,但您可能还会有一个保留周期:

__weak typeof(self) weakSelf = self;
[photo imageForFootageSize:[Footage footageSizeThatBestFitsRect:self.bounds] withCompletionHandler:^(UIImage *image) {
    if ([weakSelf.delegate respondsToSelector:@selector(galleryPhotoCollectionViewCell:didLoadImage:)])
    {
        [weakSelf.delegate galleryPhotoCollectionViewCell:weakSelf didLoadImage:image];
    }
    image = nil;
}];

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM