[PHCollectionList canContainCustomKeyAssets]:发送到实例的无法识别的选择器

[PHCollectionList canContainCustomKeyAssets]: unrecognized selector sent to instance

在最新版本的 iOS(iOS 9.2 和 iOS 9.3)上,获取 PHAssets 现在崩溃了。它以前工作正常。

我得到的错误是:

[PHCollectionList canContainCustomKeyAssets]: unrecognized selector sent to instance Terminating app due to uncaught exception 'NSInvalidArgumentException'

抛出异常的行是:

            PHFetchResult *fetchImage = [PHAsset fetchKeyAssetsInAssetCollection:(PHAssetCollection*)collection options:fetchOptions];

这里有更多代码,供参考:

Class PHPhotoLibrary_class = NSClassFromString(@"PHPhotoLibrary");
        if (PHPhotoLibrary_class) {

            PHFetchResult *fetchResult = self.collectionsFetchResults[indexPath.section];
            PHCollection *collection = fetchResult[indexPath.row];

            cell.textLabel.text = collection.localizedTitle;

            PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init];
            fetchOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:YES]];
            PHFetchResult *fetchImage = [PHAsset fetchKeyAssetsInAssetCollection:(PHAssetCollection*)collection options:fetchOptions];
            PHAsset *asset = [fetchImage firstObject];

            PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
            options.resizeMode = PHImageRequestOptionsResizeModeExact;

            CGFloat scale = [UIScreen mainScreen].scale;
            CGFloat dimension = 90.0;
            CGSize size = CGSizeMake(dimension*scale, dimension*scale);

            [[PHImageManager defaultManager] requestImageForAsset:asset
                                                       targetSize:size
                                                      contentMode:PHImageContentModeAspectFill
                                                          options:options
                                                    resultHandler:^(UIImage *result, NSDictionary *info) {
                                                        if (result) {
                                                            CGSize itemSize = CGSizeMake(60, 60);
                                                            UIGraphicsBeginImageContextWithOptions(itemSize, NO, 2);
                                                            CGRect imageRect = CGRectMake(0.0, 0.0, itemSize.width, itemSize.height);
                                                            [result drawInRect:imageRect];
                                                            cell.imageView.image  = UIGraphicsGetImageFromCurrentImageContext();
                                                            UIGraphicsEndImageContext();
                                                        }
                                                        else{
                                                            UIImage *placeholder = [UIImage imageNamed:@"image-placeholder.jpg"];
                                                            CGSize itemSize = CGSizeMake(60, 60);
                                                            UIGraphicsBeginImageContextWithOptions(itemSize, NO, 2);
                                                            CGRect imageRect = CGRectMake(0.0, 0.0, itemSize.width, itemSize.height);
                                                            [placeholder drawInRect:imageRect];
                                                            cell.imageView.image  = UIGraphicsGetImageFromCurrentImageContext();
                                                            UIGraphicsEndImageContext();
                                                        }
                                                    }];
        }

首先,使用 PHAsset 获取所有资产,如

dispatch_async(dispatch_get_main_queue(), ^{     

        AllPhotos=[[NSMutableArray alloc] init];
        PHFetchResult *result = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:nil];
        for (PHAsset *asset in result)
        {
            [AllPhotos addObject:asset];

        }
        [self.collectionView reloadData];

        // code here
    });

不是,像这样使用collectionview委托方法

  PHImageManager *manager = [PHImageManager defaultManager];
    PHAsset *asset = [AllPhotos objectAtIndex:indexPath.row];
    PHImageRequestOptions *requestOptions = [[PHImageRequestOptions alloc] init];
    requestOptions.resizeMode   = PHImageRequestOptionsResizeModeExact;
    requestOptions.deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic;
    requestOptions.synchronous = false;

    //CGFloat scale = 1.5; //or an even smaller one
    if (!manager)
    {
        manager = [[PHCachingImageManager alloc] init];
    }
    if (!requestOptions)
    {
        requestOptions = [[PHImageRequestOptions alloc] init];
    }

    [manager requestImageForAsset:asset
                       targetSize:CGSizeMake(imagesize.width,imagesize.height)
                      contentMode:PHImageContentModeAspectFill
                          options:requestOptions
                    resultHandler:^void(UIImage *image, NSDictionary *info)
     {
         [imageview setImage:image];
     }];

    [cell.contentView addSubview:imageview];

这个问题其实出在这里:

PHCollection *collection = fetchResult[indexPath.row];

然后在这里:

PHAsset *asset = [fetchImage firstObject];

您正在使用 PHCollection 获取集合,然后假设所有资产都是 PHAssets 而没有正确检查是否是这种情况。

实际上,PHCollection 有 two possible subclassesPHAssetPHCollectionListPHCollectionList 是这里抛出错误的原因。

PHCollection *collection = fetchResult[indexPath.row]; 之后包装代码并检查 PHAsset,它应该可以解决问题:

if ([collection isKindOfClass:[PHAssetCollection class]]) {
//code 
}