使用 NSPredicate 和 FourCharCodes 编写 Bridge 脚本并过滤 SBElementArrays

发布于 2024-10-09 18:06:30 字数 1964 浏览 0 评论 0原文

我是第一次尝试 Scripting Bridge,但在根据包含 FourCharCode 枚举常量作为标准的 NSPredicate 过滤 SBElementArray 时遇到了问题。

我编写了一个简单的程序来识别用户 iTunes 库中的“库”源,方法是使用 -filteredArrayUsingPredicate: 来过滤所有 iTunes 源的 SBElementArray。我期望返回一个 SBElementArray,在评估时,它会生成一个包含一个元素的数组,即库源。相反,当我对返回的 SBElementArray 调用 -get 时,我得到一个空数组。

令人困惑的是,如果更改顺序,而是对所有源的 SBElementArray 调用 -get 来获取具体的 NSArray,然后调用 - FilteredArrayUsingPredicate:在这个具有与之前相同的谓词的数组上,我确实得到了所需的结果。然而,我不认为这是必要的,并且我已经使用其他 NSPredicates 成功过滤了 SBElementArray (例如 @"name=='Library'"工作正常)。

代码片段如下。 iTunesESrcLibrary 是在 Scripting Bridge 生成的头文件中定义的 FourCharCode 常量。 (iTunesESrcLibrary = 'kLib')。我正在运行 10.6.5。

iTunesApplication* iTunes = [[SBApplication alloc] initWithBundleIdentifier:@"com.apple.iTunes"];   

NSPredicate* libraryPredicate = [NSPredicate predicateWithFormat:@"kind == %u", iTunesESrcLibrary];

SBElementArray* allSources_Attempt1 = [iTunes sources];
SBElementArray* allLibrarySources_Attempt1 = (SBElementArray*)[allSources_Attempt1 filteredArrayUsingPredicate:libraryPredicate];

NSLog(@"Attempt 1: %@", allLibrarySources_Attempt1);
NSLog(@"Attempt 1 (evaluated): %@", [allLibrarySources_Attempt1 get]);


NSArray* allSources_Attempt2 = [[iTunes sources] get];
NSArray* allLibrarySources_Attempt2 = [allSources_Attempt2 filteredArrayUsingPredicate:libraryPredicate];

NSLog(@"Attempt 2: %@", allLibrarySources_Attempt2);

我得到的输出如下:

Attempt 1: <SBElementArray @0x3091010: ITunesSource whose 'cmpd'{ 'relo':'=   ', 'obj1':'obj '{ 'want':'prop', 'from':'exmn'($$), 'form':'prop', 'seld':'pKnd' }, 'obj2':1800169826 } of application "iTunes" (88827)>
Attempt 1 (evaluated): (
)
Attempt 2: (
"<ITunesSource @0x3091f10: ITunesSource id 65 of application \"iTunes\" (88827)>"
)

I'm experimenting with Scripting Bridge for the the first time, but have run into an issue with filtering a SBElementArray according to a NSPredicate containing a FourCharCode enum constant as a criterion.

I wrote a trivial program to identify the "library" source in a user's iTunes library, by using -filteredArrayUsingPredicate: to filter the SBElementArray of all iTunes sources. I was expecting to get back an SBElementArray that, when evaluated, would produce an array of one element, namely the library source. Instead, when I call -get on the returned SBElementArray, I get back an empty array.

Perplexingly, if change the order and instead call -get on the SBElementArray of all sources to get a concrete NSArray, and call -filteredArrayUsingPredicate: on this array with the same predicate as before, I do get the desired result. I don't believe this is supposed to be necessary however, and I've had success filtering a SBElementArray using other NSPredicates (e.g. @"name=='Library'" works fine).

The code snippet is below. iTunesESrcLibrary is a FourCharCode constant defined in the header file generated by Scripting Bridge. (iTunesESrcLibrary = 'kLib'). I'm running 10.6.5.

iTunesApplication* iTunes = [[SBApplication alloc] initWithBundleIdentifier:@"com.apple.iTunes"];   

NSPredicate* libraryPredicate = [NSPredicate predicateWithFormat:@"kind == %u", iTunesESrcLibrary];

SBElementArray* allSources_Attempt1 = [iTunes sources];
SBElementArray* allLibrarySources_Attempt1 = (SBElementArray*)[allSources_Attempt1 filteredArrayUsingPredicate:libraryPredicate];

NSLog(@"Attempt 1: %@", allLibrarySources_Attempt1);
NSLog(@"Attempt 1 (evaluated): %@", [allLibrarySources_Attempt1 get]);


NSArray* allSources_Attempt2 = [[iTunes sources] get];
NSArray* allLibrarySources_Attempt2 = [allSources_Attempt2 filteredArrayUsingPredicate:libraryPredicate];

NSLog(@"Attempt 2: %@", allLibrarySources_Attempt2);

The output I get is the following:

Attempt 1: <SBElementArray @0x3091010: ITunesSource whose 'cmpd'{ 'relo':'=   ', 'obj1':'obj '{ 'want':'prop', 'from':'exmn'($), 'form':'prop', 'seld':'pKnd' }, 'obj2':1800169826 } of application "iTunes" (88827)>
Attempt 1 (evaluated): (
)
Attempt 2: (
"<ITunesSource @0x3091f10: ITunesSource id 65 of application \"iTunes\" (88827)>"
)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

不…忘初心 2024-10-16 18:06:30

我想我已经明白了。看来您不能简单地在打算用于过滤 SBElementArrayNSPredicate 中直接使用 FourCharCode 的整数值。

而不是

[NSPredicate predicateWithFormat:@"kind == %u", iTunesESrcLibrary]

一次偶然的机会,我发现您需要使用:

[NSPredicate predicateWithFormat:@"kind == %@", [NSAppleEventDescriptor descriptorWithTypeCode: iTunesESrcLibrary]]

:使用第二种形式,我可以按预期过滤 SBElementArray 源列表。但是,这个新谓词不能用于过滤 NSArray,即使该数组只是 SBElementArray 的计算形式!这里,你必须切换回%u版本。

咆哮:
坦率地说,这很糟糕,而且这似乎是 Scripting Bridge 应该处理的事情,所以我不必这样做;我不必知道 NSAppleEventDescriptor 是什么。虽然并非所有适用于 NSArray 的谓词都适用于 SBElementArray,这是合理的,但反之则不应该如此,而且这样会造成不必要的混乱。

I think I've figured it out. It seems you can't simply use a FourCharCode's integer value directly in a NSPredicate that you intend to use to filter an SBElementArray.

By chance, I found that instead of:

[NSPredicate predicateWithFormat:@"kind == %u", iTunesESrcLibrary]

you need to use:

[NSPredicate predicateWithFormat:@"kind == %@", [NSAppleEventDescriptor descriptorWithTypeCode: iTunesESrcLibrary]]

Using this second form, I can filter the SBElementArray sources list as expected. However, this new predicate can't be used to filter the NSArray, even though this array is just the evaluated form of the SBElementArray! Here, you have to switch back to the %u version.

Rant:
Frankly this sucks, and it seems the sort of thing Scripting Bridge should deal with so I don't have to; I shouldn't have to know what an NSAppleEventDescriptor is. And while it's reasonable that not all predicates that work with NSArray should work with SBElementArray, the converse should not be the case and it's unnecessarily confusing that it is.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文