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];
我有一段代码应该查询 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];