1

我正在尝试通过 Scripting Bridge 从 iTunes 中获取曲目列表。我正在使用NSPredicate,因为这是推荐的方式。这在某些情况下效果很好,而在其他情况下却非常缓慢。例如,这将很快执行:

NSString *formatString = @"artist == ABC AND album == XYZ";
NSPredicate *trackFilter = [NSPredicate predicateWithFormat:formatString];
NSArray *tracksToPlay = [[libraryPlaylist fileTracks] filteredArrayUsingPredicate:trackFilter];

libraryPlaylist是在别处创建的 iTunesLibraryPlaylist 对象。)

但如果我添加其中一个kindvideoKind混合,iTunes 会在一分钟或更长时间内达到 100% CPU。

NSString *formatString = @"artist == ABC AND album == XYZ AND kind != 'PDF document' AND videoKind == %@", ;
NSPredicate *trackFilter = [NSPredicate predicateWithFormat:formatString, [NSAppleEventDescriptor descriptorWithTypeCode:iTunesEVdKNone]];
NSArray *tracksToPlay = [[libraryPlaylist fileTracks] filteredArrayUsingPredicate:trackFilter];

但这最终会奏效。真正的失败是albumArtist。如果我尝试

NSString *formatString = @"albumArtist == ABC AND album == XYZ";
NSPredicate *trackFilter = [NSPredicate predicateWithFormat:formatString];
NSArray *tracksToPlay = [[libraryPlaylist fileTracks] filteredArrayUsingPredicate:trackFilter];

iTunes 将达到 100% CPU 并坐在那里不知道多久。(我在 3 或 4 分钟后放弃了。)我是否遗漏了什么或者这是 iTunes 中的错误?

附加信息

我的代码采用生成的曲目并调用另一种方法将它们添加到播放列表(也使用脚本桥)。我注意到,当尝试按种类过滤时,曲目会慢慢地一一出现在列表中,而 iTunes 会敲击 CPU。这只能意味着它filteredArrayUsingPredicate已经返回了它的结果,那么iTunes如此努力的工作是什么?

4

1 回答 1

0

另一个帖子间接帮助我找到了答案。

使用“图书馆”播放列表会导致许多不寻常的问题。使用“音乐”播放列表似乎可以解决它们。在上面的示例中,设置libraryPlaylist这种方式是导致问题的原因:

iTunesApplication *iTunes = [SBApplication applicationWithBundleIdentifier:@"com.apple.iTunes"];
iTunesSource *library = [[[[iTunes sources] get] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"kind == %i", iTunesESrcLibrary]] objectAtIndex:0];
iTunesLibraryPlaylist *libraryPlaylist = [[[library libraryPlaylists] objectAtIndex:0];

答案是获取“音乐”播放列表而不是“图书馆”播放列表:

iTunesApplication *iTunes = [SBApplication applicationWithBundleIdentifier:@"com.apple.iTunes"];
iTunesSource *library = [[[[iTunes sources] get] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"kind == %i", iTunesESrcLibrary]] objectAtIndex:0];
iTunesLibraryPlaylist *libraryPlaylist = [[[[library playlists] get] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"specialKind == %i", iTunesESpKMusic]] objectAtIndex:0];
其他需要注意的事项

原始问题中的"albumArtist == ABC AND album == XYZ"过滤器实际上运行得非常快。缓慢的是你对结果所做的任何事情。立即致电get是部分解决方案。(get运行速度和其他任何东西一样慢,但是通过预先执行,您可以将速度限制为单个操作。另请注意,它get仅适用于SBElementArray.)

我还发现调用fileTracks重新引入了一些缓慢。改用tracks可以解决这个问题。所以过滤器应该是:

NSArray *tracksToPlay = [(SBElementArray *)[[libraryPlaylist tracks] filteredArrayUsingPredicate:trackFilter] get];

(使用“图书馆”时,只会fileTracks返回带有location属性的对象,您需要将其添加到播放列表中。切换到“音乐”后,tracks似乎也返回带有位置的对象。)

于 2012-01-19T19:43:23.593 回答