Error: 'Unsupported predicate in fetch options

2019-03-15 06:24发布

问题:

I'm trying to use smartAlbum to generate an array of either only videos or only photos or both.
You can see my code below:

    PHFetchResult *collectionList = [PHCollectionList fetchMomentListsWithSubtype:PHCollectionListSubtypeMomentListCluster options:nil];
    PHFetchOptions *options = nil;
        if (self.xSelected) {
            options = [[PHFetchOptions alloc] init];
            options.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:NO]];
            options.predicate = [NSPredicate predicateWithFormat:@"mediaType = %d",PHAssetMediaTypeImage];
        }
        if (self.ySelected) {
            options = [[PHFetchOptions alloc] init];
            options.predicate = [NSPredicate predicateWithFormat:@"mediaType = %d",PHAssetMediaTypeVideo];
        }

    [collectionList enumerateObjectsUsingBlock:^(PHCollectionList *collection, NSUInteger idx, BOOL *stop) {
        PHFetchResult *momentsInCollection = [PHAssetCollection fetchMomentsInMomentList:collection options:options];
        for (id moment in momentsInCollection) {
            PHAssetCollection *castedMoment = (PHAssetCollection *)moment;
            [_smartAlbums insertObject:castedMoment atIndex:0];
        }
    }];


This however is constantly breaking on the first line inside the block and giving the following error: Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unsupported predicate in fetch options: mediaType == 2'

I did a little research and found this link.
I'm wondering if this is an Apple bug or if its just something wrong with my code.
It seems like it worked for the people that referred to this answer, which is so weird coz its basically the same thing.


Thanks in advance,
Anish

EDIT:
I think I found the answer here in Apple's Documentation. Looks like mediaType is a key only for PHAsset and not PHAssetCollection. So now I guess the question is how to get PFAssetCollection with only videos or only images.

回答1:

Use this method to get photos and videos assets array separately.

Get All Videos

func getAllVideos(completion:@escaping  (_ videoAssets : [PHAsset]?) -> Void) {
    var videoAssets : [PHAsset] = []

    let fetchOptions = PHFetchOptions()
    fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate",ascending: false)]
    fetchOptions.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.video.rawValue)
    let allVideo = PHAsset.fetchAssets(with: .video, options: fetchOptions)
    allVideo.enumerateObjects { (asset, index, bool) in
        videoAssets.append(asset)
    }
    completion(videoAssets)
}

Get All Photos

func getAllPhotos(completion:@escaping  (_ photosAssets : [PHAsset]?) -> Void) {
    var photosAssets : [PHAsset] = []

    let fetchOptions = PHFetchOptions()
    let scale = UIScreen.main.scale
    let screenWidth = UIScreen.main.bounds.width * scale
    let screenHeight = UIScreen.main.bounds.height  * scale

    fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate",ascending: false)]
    fetchOptions.predicate = NSPredicate(format: "mediaType = %d || (mediaSubtype & %d) != 0 && (pixelHeight != %d AND pixelWidth != %d) OR (pixelHeight != %d AND pixelWidth != %d)", PHAssetMediaType.image.rawValue, PHAssetMediaSubtype.photoLive.rawValue ,screenHeight, screenWidth, screenWidth, screenHeight)

    let allPhotos = PHAsset.fetchAssets(with: .image, options: fetchOptions)
    allPhotos.enumerateObjects { (asset, index, bool) in
        photosAssets.append(asset)
    }
    completion(photosAssets)
}