Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何使用PhotoKit减少内存使用?_Ios_Objective C_Photokit - Fatal编程技术网

Ios 如何使用PhotoKit减少内存使用?

Ios 如何使用PhotoKit减少内存使用?,ios,objective-c,photokit,Ios,Objective C,Photokit,我正在使用PhotoKit从系统相册中获取照片,并将其放入UICollectionView中 对于UICollectionViewCell,我将其设置为: cell.imageView.contentMode = UIViewContentModeScaleAspectFill; -(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPa

我正在使用
PhotoKit
从系统相册中获取照片,并将其放入
UICollectionView

  • 对于
    UICollectionViewCell
    ,我将其设置为:

    cell.imageView.contentMode = UIViewContentModeScaleAspectFill;
    
    -(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
    {
        MYCell *cell = (MYCell *)[collectionView dequeueReusableCellWithReuseIdentifier:@"reuseCell" forIndexPath:indexPath];
    
        CGFloat scale = [UIScreen mainScreen].scale;
        CGSize targetSize = CGSizeMake(_layout.itemSize.width*scale, _layout.itemSize.height*scale);
    
        PHAsset *asset = _fetchedPhotos[indexPath.item];
        [_manager requestImageForAsset:asset targetSize:targetSize contentMode:PHImageContentModeAspectFill options:_options resultHandler:^(UIImage *result, NSDictionary *info) {
             cell.imageView.image = result;
        }];
    
        return cell;
    }
    
  • 初始化我的
    UICollectionView
    时,我仅从
    collection
    中获取照片
    PHAsset
    摄像机卷

    PHFetchResult *fetchResult = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
    [fetchResult enumerateObjectsUsingBlock:^(PHAssetCollection *collection, NSUInteger idx, BOOL *stop) {
        NSLog(@"ALBUM NAME: %@", collection.localizedTitle);
        if ([collection.localizedTitle isEqualToString:@"Camera Roll"]) {
            _fetchedPhotos = [PHAsset fetchAssetsInAssetCollection:collection options:nil];
            _pickedStatuses = @[].mutableCopy;            
    
            NSMutableArray *assets = @[].mutableCopy;
    
            _manager = [[PHCachingImageManager alloc] init];
            _options = [[PHImageRequestOptions alloc] init];
            _options.resizeMode = PHImageRequestOptionsResizeModeExact;
            _options.deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic;
    
            CGFloat scale = [UIScreen mainScreen].scale;
            CGSize targetSize = CGSizeMake(layout.itemSize.width*scale, layout.itemSize.height*scale);
    
            //I'm not sure if this api should be called here
            [_manager startCachingImagesForAssets:assets targetSize:targetSize contentMode:PHImageContentModeAspectFill options:_options];
        }
    }];
    
  • 然后我从上面的
    PHFetchResult
    请求
    UIImage
    ,如下所示:

    cell.imageView.contentMode = UIViewContentModeScaleAspectFill;
    
    -(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
    {
        MYCell *cell = (MYCell *)[collectionView dequeueReusableCellWithReuseIdentifier:@"reuseCell" forIndexPath:indexPath];
    
        CGFloat scale = [UIScreen mainScreen].scale;
        CGSize targetSize = CGSizeMake(_layout.itemSize.width*scale, _layout.itemSize.height*scale);
    
        PHAsset *asset = _fetchedPhotos[indexPath.item];
        [_manager requestImageForAsset:asset targetSize:targetSize contentMode:PHImageContentModeAspectFill options:_options resultHandler:^(UIImage *result, NSDictionary *info) {
             cell.imageView.image = result;
        }];
    
        return cell;
    }
    
  • 但当我运行它并足够快地滚动
    UICollectionView
    时,我发现内存使用变得如此急剧:

    cell.imageView.contentMode = UIViewContentModeScaleAspectFill;
    
    -(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
    {
        MYCell *cell = (MYCell *)[collectionView dequeueReusableCellWithReuseIdentifier:@"reuseCell" forIndexPath:indexPath];
    
        CGFloat scale = [UIScreen mainScreen].scale;
        CGSize targetSize = CGSizeMake(_layout.itemSize.width*scale, _layout.itemSize.height*scale);
    
        PHAsset *asset = _fetchedPhotos[indexPath.item];
        [_manager requestImageForAsset:asset targetSize:targetSize contentMode:PHImageContentModeAspectFill options:_options resultHandler:^(UIImage *result, NSDictionary *info) {
             cell.imageView.image = result;
        }];
    
        return cell;
    }
    


    如果内存不足,它会崩溃,我如何减少它呢?

    我现在所做的是

  • 减少获取的
    PHAsset
    对象的目标大小
  • 尝试采用缓存。我的代码如下:

    CGFloat scale = 1.5; //or an even smaller one
    if (!_manager) {
        _manager = [[PHCachingImageManager alloc] init];
    }
    if (!_options) {
        _options = [[PHImageRequestOptions alloc] init];
    }
    _options.resizeMode = PHImageRequestOptionsResizeModeExact;
    _options.deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic;
    
    NSRange range = NSMakeRange(0, _fetchedPhotos.count);
    NSIndexSet *set = [NSIndexSet indexSetWithIndexesInRange:range];
    NSArray *assets = [_fetchedPhotos objectsAtIndexes:set];
    
    CGSize targetSize = CGSizeMake(_layout.itemSize.width*scale, _layout.itemSize.height*scale);
    
    [_manager startCachingImagesForAssets:assets targetSize:targetSize contentMode:PHImageContentModeAspectFill options:_options];
    
  • 现在,即使我以足够快的速度滚动
    UICollectionView
    ,顶部内存也将小于
    50MB
    ,多亏了
    缓存
    (我猜它是基于我的代码工作的),它的波动性不会太大,内存使用如下:

    cell.imageView.contentMode = UIViewContentModeScaleAspectFill;
    
    -(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
    {
        MYCell *cell = (MYCell *)[collectionView dequeueReusableCellWithReuseIdentifier:@"reuseCell" forIndexPath:indexPath];
    
        CGFloat scale = [UIScreen mainScreen].scale;
        CGSize targetSize = CGSizeMake(_layout.itemSize.width*scale, _layout.itemSize.height*scale);
    
        PHAsset *asset = _fetchedPhotos[indexPath.item];
        [_manager requestImageForAsset:asset targetSize:targetSize contentMode:PHImageContentModeAspectFill options:_options resultHandler:^(UIImage *result, NSDictionary *info) {
             cell.imageView.image = result;
        }];
    
        return cell;
    }
    

    更新
    根据另一篇帖子,建议不要指定
    PHImageRequestOptions
    对象。相反,你可以让iOS来决定什么是最适合你的,以最好的质量和最短的时间展示照片。

    我建议你看看我提到的答案。这不仅可以帮助您进行缓存,苹果的照片框架示例也可以帮助您解决任何问题。

    我期望这种模式,因为在PhotoKit创建缩略图之前,它必须将整个图像加载到内存中。另外,您是在设备上测试还是在模拟器中测试?两者之间的内存行为会有很大的不同,所以总是在设备上测试,以获得应用程序性能的真实图片。我总是在我的iPhone 6 Plus设备上测试它。