我正试图通过Scripting Bridge从iTunes中获取一系列曲目。我正在使用NSPredicate
,因为那是the recommended way。这在某些情况下非常有效,而在其他情况下则非常慢。例如,这将很快执行:
NSString *formatString = @"artist == ABC AND album == XYZ";
NSPredicate *trackFilter = [NSPredicate predicateWithFormat:formatString];
NSArray *tracksToPlay = [[libraryPlaylist fileTracks] filteredArrayUsingPredicate:trackFilter];
(libraryPlaylist
是在其他地方创建的iTunesLibraryPlaylist对象。)
但如果我在混音中添加kind
或videoKind
,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中的错误吗?
我的代码获取生成的曲目并调用另一种方法将它们添加到播放列表(也使用Scripting Bridge)。我注意到当尝试按类型过滤时,轨道会逐渐弹出到列表中,而iTunes则敲击了CPU。这只能意味着filteredArrayUsingPredicate
已经返回了它的结果,那么iTunes如何努力工作呢?
答案 0 :(得分:0)
Another post间接帮助我找到答案。
使用“库”播放列表会导致许多异常问题。使用“音乐”播放列表似乎可以修复它们。在上面的示例中,以这种方式设置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
似乎也返回带有位置的对象。)