一些标准使用Scripting Bridge和NSPredicate来ping CPU

时间:2011-11-25 18:39:05

标签: cocoa itunes nspredicate scripting-bridge

我正试图通过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对象。)

但如果我在混音中添加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中的错误吗?

其他信息

我的代码获取生成的曲目并调用另一种方法将它们添加到播放列表(也使用Scripting Bridge)。我注意到当尝试按类型过滤时,轨道会逐渐弹出到列表中,而iTunes则敲击了CPU。这只能意味着filteredArrayUsingPredicate已经返回了它的结果,那么iTunes如何努力工作呢?

1 个答案:

答案 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似乎也返回带有位置的对象。)