2

我正在使用以下方法来请求一些照片并将它们添加到数组中以供以后使用:

-(void) fetchImages{

        self.assets = [[PHFetchResult alloc]init];
        PHFetchOptions *options = [[PHFetchOptions alloc] init];
        options.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:YES]];
        self.assets = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:options];

        self.photosToVideofy = [[NSMutableArray alloc]init];

        CGSize size = CGSizeMake(640, 480);
        PHImageRequestOptions *photoRequestOptions = [[PHImageRequestOptions alloc]init];
        photoRequestOptions.synchronous = YES;

        for (NSInteger i = self.firstPhotoIndex; i < self.lastPhotoIndex; i++)
        {
            PHAsset *asset = self.assets[i];
            [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:size contentMode:PHImageContentModeAspectFit options:photoRequestOptions resultHandler:^(UIImage *result, NSDictionary *info) {
                if (result) {
                    [self.photosToVideofy addObject:result];


                }
            }];
        }
        NSLog(@"There are %lu photos to Videofy", (unsigned long)self.photosToVideofy.count);

}

当照片数量少于 50 张时,这可以正常工作。在内存跳转到 150-160mb 之后,我收到消息Connection to assetsd was interrupted or assetsd died并且应用程序崩溃。在获得我想要的资产后,如何从内存中释放资产 (PHFetchResult)?(我需要吗?)我希望最多可以添加 150 张照片。有任何想法吗?谢谢

4

4 回答 4

2

您不应将 PHFetchResult 的结果放入数组中。PHFetchResult 的想法是指向照片库中的许多图像,而不将它们全部存储在 RAM 中,(我不确定它是如何做到的)只需像数组一样使用 PHFetchResult 对象,它会为您处理内存问题。例如,将 collectionViewController 直接连接到 PHFetchResult 对象,并使用 PHImageManager 仅请求可见单元格的图像等。

来自苹果文档:“但是,与 NSArray 对象不同,PHFetchResult 对象根据需要从照片库中动态加载其内容,即使在处理大量结果时也能提供最佳性能。” https://developer.apple.com/library/ios/documentation/Photos/Reference/PHFetchResult_Class/

于 2015-11-11T20:46:20.587 回答
1

您在 fetchImages 方法中的代码需要一些重构,看看这个建议:

-(void) fetchImages {

    PHFetchOptions *options = [[PHFetchOptions alloc] init];
    options.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:YES]];
    PHFetchResult *assets = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:options];

    self.photosToVideofy = [[NSMutableArray alloc] init];

    CGSize size = CGSizeMake(640, 480);
    PHImageRequestOptions *photoRequestOptions = [[PHImageRequestOptions alloc] init];
    photoRequestOptions.synchronous = YES;

    for (NSInteger i = self.firstPhotoIndex; i < self.lastPhotoIndex; i++)
    {
        PHAsset *asset = assets[i];
        [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:size contentMode:PHImageContentModeAspectFit options:photoRequestOptions resultHandler:^(UIImage *result, NSDictionary *info) {
            if (result) {
                [self.photosToVideofy addObject:result];


            }
        }];
    }
    NSLog(@"There are %lu photos to Videofy", (unsigned long)self.photosToVideofy.count);
}

但问题是内存消耗。让我们做一些计算。

单个图像,使用 ARGB 和每像素 4 字节:

640x480x4 = 1.2MB

现在,您想在 RAM 中存储 150 张图像,因此:

150x1.2MB = 180MB

例如,如果您使用超过 300 MB 的内存,具有 512 MB 的 iPhone 4 会崩溃,但如果其他应用程序也消耗大量 RAM,则可能会更少。

我认为,您应该考虑将图像存储到文件而不是 RAM。

于 2014-11-05T11:25:09.350 回答
0

这可能是故意的(如果不查看其余代码就无法判断),但是 self.photosToVideofy 永远不会被释放:因为您在一个块中访问它,所以您将块传递给的对象([PHImageManager defaultManager] ) 将始终引用数组。

完成图像后,尝试显式清除数组。数组本身仍然不会被释放,但它包含的对象将(或者如果它们没有在其他任何地方引用,则可以)。

最好的解决方案是从块中删除数组。但是,这需要更改代码的逻辑。

于 2014-11-05T11:38:58.560 回答
0

你必须设置

photoRequestOptions.synchronous = NO;

代替

photoRequestOptions.synchronous = YES;

为我工作,iOS 10.2

于 2017-02-09T15:26:24.890 回答