MPMediaQuery addFilterPredicate从智能播放列表

时间:2017-03-21 15:28:27

标签: ios objective-c itunes

我有一段代码应该在iOS设备上查询音乐库并返回其内容的子集。当为播放列表触发此代码时,我创建一个MPMediaQuery,然后使用MPMediaPropertyPredicate应用一系列过滤器。首先,我过滤我想要的内容类型(音乐),然后我删除所有云内容,最后,当浏览播放列表时,我过滤属于该播放列表的项目。这一切都很好 - 除了智能播放列表(甚至它在某些设备上工作)。下面是代码 - 我可以看到在前两个过滤器之后我仍然有大量项目(10107),但在应用了最终过滤器后,当我的查询是智能播放列表时,我的查询减少为0项。我以为有某种整数溢出,所以我改变了"值"是一个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"

RecentPlayed" 9690568479441451478"

RecentAdded" 9690568479441451479"

5stars" 9690568479441451476"

删除iCloud过滤后,所有智能播放列表都会加载播放列表的内容" 5Stars"。

1 个答案:

答案 0 :(得分:0)

想出来了!

ID需要是一个无符号长号来保存那么大的数字:

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