MPMediaQuery addFilterPredicate 从智能播放列表的查询中删除所有项目

MPMediaQuery addFilterPredicate removing all items from query from Smart Playlist

我有一段代码应该查询 iOS 设备上的音乐库和 return 其内容的一个子集。当针对播放列表触发此代码时,我创建一个 MPMediaQuery,然后使用 MPMediaPropertyPredicate 应用一系列过滤器。首先,我过滤我想要的内容类型(音乐),然后删除所有云内容,最后,在浏览播放列表时,我过滤属于该播放列表的项目。这一切都很好——除了在智能播放列表上(即使在某些设备上也能正常工作)。下面是代码——我可以看到在前两个过滤器之后我仍然有大量的项目列表 (10107),但是在应用最后一个过滤器之后,当它是一个智能播放列表时我的查询减少到 0 个项目。我认为发生了某种整数溢出,所以我将 "value" 更改为 NSDecimalNumber 而不是 NSNumber,并且我总是将完整的播放列表 ID 视为整数,而不是科学计数法,但它没有解决问题。知道发生了什么事吗?

- (MPMediaQuery*) queryFromObjectId:(NSString*)objectId
{

NSLog(@"INSIDE queryFromObjectId %@", objectId);

NSString *s;

MPMediaQuery* rv = [MPMediaQuery new];

NSURL* url = [NSURL URLWithString:objectId];
NSString* type = url.host;

NSLog(@"URL: %@, type: %@", url, type);

NSArray* rootItem = [self.rootDict objectForKey:type];
if (rootItem != nil) {
    rv.groupingType = [rootItem[kRootIndexQuery] groupingType];
}

NSDictionary *parameters = [url nvt_queryDictionary];

MPMediaPropertyPredicate* pred;

// Filter proper media types
if (parameters[MPMediaItemPropertyPodcastPersistentID] || rv.groupingType == MPMediaGroupingPodcastTitle) {
    NSLog(@"Filtering for Podcast type");
    pred = [MPMediaPropertyPredicate predicateWithValue:[NSNumber numberWithInt:MPMediaTypePodcast] forProperty:MPMediaItemPropertyMediaType];
} else {
    NSLog(@"Filtering for music/media type");
    pred = [MPMediaPropertyPredicate predicateWithValue:[NSNumber numberWithInt:MPMediaTypeMusic] forProperty:MPMediaItemPropertyMediaType];
}
[rv addFilterPredicate:pred];

// Filter iCloud items
if ([UIDevice currentDevice].systemVersion.floatValue >= 6) {
    NSLog(@"Filtering iCloud items");
    pred = [MPMediaPropertyPredicate predicateWithValue:[NSNumber numberWithBool:NO] forProperty:MPMediaItemPropertyIsCloudItem];
    [rv addFilterPredicate:pred];
}

int index = 0;
for (NSString *key in parameters.allKeys) {

    NSLog(@"Inside for loop, KEY: %@, index: %d", key, index);
    MPMediaPropertyPredicate *pred;

    if ([key isEqualToString:MPMediaPlaylistPropertyPersistentID] || [key isEqualToString:MPMediaItemPropertyPodcastPersistentID]) {
        NSLog(@"IF inside FOR");
        NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
        formatter.numberStyle = NSNumberFormatterDecimalStyle;
//            NSNumber *value = [formatter numberFromString:parameters[key]];
        NSDecimalNumber *value = [NSDecimalNumber decimalNumberWithString:parameters[key]];
        pred = [MPMediaPropertyPredicate predicateWithValue:value forProperty:key];
    }

    else {
        NSLog(@"ELSE inside FOR");
        id value = parameters[key];
        pred = [MPMediaPropertyPredicate predicateWithValue:value forProperty:key];
    }

    s = [NSString stringWithFormat:@"BEFORE FILTER items:%u",  rv.items.count];
    NSLog(s);

    s = [NSString stringWithFormat:@"Predicate: value: %@, key: %@", pred.value, pred.property];
    NSLog(s);

    [rv addFilterPredicate:pred];

    s = [NSString stringWithFormat:@"AFTER FILTER items:%u",  rv.items.count];
    NSLog(s);

    index++;
}

return rv;
}

在我看到的日志中:

2017-03-21 11:09:26.090316 T[1978:1214332] INSIDE queryFromObjectId //Tracks?playlistPersistentID=9690568479441451477
2017-03-21 11:09:26.090549 T[1978:1214332] URL: //Tracks?playlistPersistentID=9690568479441451477, type: Tracks
2017-03-21 11:09:26.090690 T[1978:1214332] Filtering for music/media type
2017-03-21 11:09:26.090846 T[1978:1214332] Filtering iCloud items
2017-03-21 11:09:26.090967 T[1978:1214332] Inside for loop, KEY: playlistPersistentID, index: 0
2017-03-21 11:09:26.091017 T[1978:1214332] IF inside FOR
2017-03-21 11:09:26.091200 T[1978:1214332] BEFORE FILTER items:10107
2017-03-21 11:09:26.091298 T[1978:1214332] Predicate: value: 9690568479441451477, key: playlistPersistentID
2017-03-21 11:09:26.091765 T[1978:1214332] AFTER FILTER items:0

这一切都非常适合非智能播放列表。

此外,如果我删除 iCloud 过滤部分——这似乎什么都不做——所有智能播放列表都会加载...但加载相同的内容:具有最小 ID 的智能播放列表的内容.以下是我正在测试的播放列表的名称和 ID:

Top500MostPlayed“9690568479441451477”

最近播放“9690568479441451478”

最近添加“9690568479441451479”

5 星“9690568479441451476”

移除iCloud过滤后,所有智能播放列表加载播放列表“5Stars”的内容。

想通了!

ID 需要是无符号长整数才能容纳这么大的数字:

        unsigned long long valueLong = strtoull([parameters[key] UTF8String], NULL, 0);
        NSNumber *value = [NSNumber numberWithUnsignedLongLong:valueLong];
        pred = [MPMediaPropertyPredicate predicateWithValue:value forProperty:key];