13

How do I filter by media subtype using NSPredicate with PHFetchOptions? I'm trying to exclude slow mo (high frame rate) and time lapse videos. I keep getting strange results when I try to use the predicate field of PHFetchOptions.

My phone has a bunch (120+) regular videos, and one slow mo video. When I run the example from Apple's docs, I get the correct result back: 1 slow mo video.

PHFetchOptions *options = [PHFetchOptions new];
options.predicate = [NSPredicate predicateWithFormat:@"(mediaSubtype & %d) != 0 || (mediaSubtype & %d) != 0", PHAssetMediaSubtypeVideoTimelapse, PHAssetMediaSubtypeVideoHighFrameRate];

But I'm trying to exclude slow mo, rather than select it. However if I negate the filter condition, I get zero results back:

options.predicate = [NSPredicate predicateWithFormat:@"(mediaSubtype & %d) == 0", PHAssetMediaSubtypeVideoHighFrameRate];

<PHFetchResult: 0x1702a6660> count=0

Confusingly, the Apple docs list the name of the field as mediaSubtypes (with an "s"), while their sample predicate is filtering on mediaSubtype (without an "s").

Trying to filter on mediaSubtypes produces an error:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Can't do bit operators on non-numbers'

Has anyone been able to make heads or tails of this predicate?

4

1 回答 1

8

首先,让我谈谈可用的,s并且只有 Apple 的 Photos 团队知道为什么以及如何在没有.mediaSubtypesPHAssetmediaSubtypes

@property (nonatomic, assign, readonly) PHAssetMediaType mediaType;
@property (nonatomic, assign, readonly) PHAssetMediaSubtype mediaSubtypes;

现在让我尝试解释为什么它不能按预期工作。以下是使用 NS_OPTIONS 或任何其他按位运算进行比较的方法。

PHAsset* asset = // my asset;
if((asset.mediaSubtypes & PHAssetMediaSubtypePhotoScreenshot) == PHAssetMediaSubtypePhotoScreenshot) {
    // This is a screenshot
}

以下是您将如何比较资产是否不是屏幕截图 -

PHAsset* asset = // my asset;
if(!((asset.mediaSubtypes & PHAssetMediaSubtypePhotoScreenshot) == PHAssetMediaSubtypePhotoScreenshot)) {
// This is not a screenshot
}

现在,在您的情况下,谓词应该是-

  • 获取所有高帧率视频

    [NSPredicate predicateWithFormat:@"((mediaSubtype & %d) == %d)", PHAssetMediaSubtypeVideoHighFrameRate, PHAssetMediaSubtypeVideoHighFrameRate];
    
  • 获取所有没有高帧率的视频

    [NSPredicate predicateWithFormat:@"!((mediaSubtype & %d) == %d)", PHAssetMediaSubtypeVideoHighFrameRate, PHAssetMediaSubtypeVideoHighFrameRate];
    

这在我的情况下非常有效。希望它可以帮助别人。

于 2016-09-08T12:16:24.027 回答