我在 StackOverflow 和其他地方浏览了大量与 Scripting Bridge 相关的线程,但似乎无法在弄清楚为什么对 Finder 进行 Scripting Bridge 调用的 Cocoa 代码块不再正常工作方面取得任何进展10.6 以下。 (类似版本的代码似乎在 10.5 下工作正常,我不知道是什么导致了行为的变化。)
基本上,我正在尝试访问 Finder 窗口的一些显示选项。我有以下代码块作为我的测试用例。我将其指向一个显示为图标的文件夹,当我运行代码时,没有任何错误块发生,但我总是在结尾。
// Set up the Scripting Bridge
FinderApplication *finder = [SBApplication applicationWithBundleIdentifier:@"com.apple.finder"];
// Get an HFS-style reference to a specified folder
// (folderPath is an NSString * containing a POSIX-style path to a folder)
NSURL *folderURL = [NSURL fileURLWithPath:folderPath];
NSString *folderPathHFS = (NSString *)CFURLCopyFileSystemPath((CFURLRef)folderURL, kCFURLHFSPathStyle);
// Get the Finder-native folder reference
FinderFolder* folder = [[finder folders] objectAtLocation:folderPathHFS];
if (folder == nil) {
NSLog(@"folder error: %@", [[folder lastError] localizedDescription]);
return;
}
// Get the Finder-native container window associated with the folder
[folder openUsing:finder withProperties:nil];
FinderFinderWindow *folderWindow = [[folder containerWindow] get];
if (folderWindow == nil) {
NSLog(@"folderWindow error: %@", [[folderWindow lastError] localizedDescription]);
return;
}
// Retrieve the view preferences for the folder
FinderIconViewOptions *ivo = [folderWindow iconViewOptions];
if (ivo == nil) {
NSLog(@"ivo error: %@", [[ivo lastError] localizedDescription]);
}
// Get the current icon size
int iconSize = (int)[ivo iconSize];
// Display the icon size in our label
if (iconSize > 0) {
NSLog(@"successfully retrieved icon size: %d", iconSize);
} else {
NSLog(@"couldn't retrieve icon size");
}
即使指向同一个文件夹,此代码的纯 AppleScript 版本也能正常工作:
tell application "Finder"
set aFolder to the folder "<HFS path to folder in question>"
set aFolderWindow to the container window of aFolder
set aIVO to the icon view options of aFolderWindow
return the icon size of aIVO
end tell
我的直觉是,某些东西在通过脚本桥时正在被奇怪地转换或转换,但我完全不知道要检查什么或者还有其他地方可以看。我尝试在从 Finder 检索对象时打印出类名,并将 [SBObject *get]
调用标记到各种与 SB 相关的赋值语句的末尾,但无济于事。
有什么想法吗?
更新
好的,所以我已经发现了上面代码中生成错误的位置,尽管我觉得我距离修复问题还差得远。问题。事实证明,脚本桥的惰性评估掩盖了问题。如果在检索对 FinderWindow 的引用后,插入以下两行代码:
NSString *test = [folderWindow name];
NSLog(@"Return value == %@; error message == %@", test, [[folderWindow lastError] localizedDescription]);
然后,Scripting Bridge 尝试实际执行名称检索,失败了,然后出现返回一条更具建设性的错误消息:
Return value == (null);错误消息==操作无法完成。 (OSStatus 错误 -1700。)
这太棒了(进步?!),但仍然没有让我更接近解决问题。该错误消息似乎表明某个地方存在 AEcoercion 问题,但我不确定如何继续解决它。生成的 Finder.h 文件(以及 Finder 的 AppleScript 字典)都非常清楚地表明我应该返回对 FinderWindow 对象的引用,并且打印 folderWindow
对象似乎可以验证这一点在 name
调用之前一切正常。
I've been skimming lots and lots of Scripting Bridge-related threads on StackOverflow and elsewhere, and can't seem to make any headway on figuring out why a block of Cocoa code that makes a Scripting Bridge call to the Finder no longer works correctly under 10.6. (A similar version of the code seemed to work OK under 10.5, and I don't know what caused the change in behavior.)
Basically, I'm trying to access some of the display options for a Finder window. I have the following block of code as my test case. I'm pointing it at a folder that is displaying as icons, and when I run the code, none of the error blocks trip, but I always just get a nonsensical response (iconSize = 0) at the end.
// Set up the Scripting Bridge
FinderApplication *finder = [SBApplication applicationWithBundleIdentifier:@"com.apple.finder"];
// Get an HFS-style reference to a specified folder
// (folderPath is an NSString * containing a POSIX-style path to a folder)
NSURL *folderURL = [NSURL fileURLWithPath:folderPath];
NSString *folderPathHFS = (NSString *)CFURLCopyFileSystemPath((CFURLRef)folderURL, kCFURLHFSPathStyle);
// Get the Finder-native folder reference
FinderFolder* folder = [[finder folders] objectAtLocation:folderPathHFS];
if (folder == nil) {
NSLog(@"folder error: %@", [[folder lastError] localizedDescription]);
return;
}
// Get the Finder-native container window associated with the folder
[folder openUsing:finder withProperties:nil];
FinderFinderWindow *folderWindow = [[folder containerWindow] get];
if (folderWindow == nil) {
NSLog(@"folderWindow error: %@", [[folderWindow lastError] localizedDescription]);
return;
}
// Retrieve the view preferences for the folder
FinderIconViewOptions *ivo = [folderWindow iconViewOptions];
if (ivo == nil) {
NSLog(@"ivo error: %@", [[ivo lastError] localizedDescription]);
}
// Get the current icon size
int iconSize = (int)[ivo iconSize];
// Display the icon size in our label
if (iconSize > 0) {
NSLog(@"successfully retrieved icon size: %d", iconSize);
} else {
NSLog(@"couldn't retrieve icon size");
}
The pure AppleScript version of this code works fine, even when pointing to the same folder:
tell application "Finder"
set aFolder to the folder "<HFS path to folder in question>"
set aFolderWindow to the container window of aFolder
set aIVO to the icon view options of aFolderWindow
return the icon size of aIVO
end tell
My gut instinct is that something is being cast or converted oddly as it's passing through the Scripting Bridge, but I'm completely out of ideas about what to check or where else to look. I've tried printing out class names along the way as objects are retrieved from the Finder and tagging [SBObject *get]
calls onto the end of various SB-related assignment statements, but to no avail.
Any ideas?
UPDATE
OK, so I've discovered where the error is being generated in the code above, although I don't feel like I'm all that much closer to fixing the problem. It turns out that the Scripting Bridge's lazy evaluation was masking the problem. If, after retrieving the reference to the FinderWindow, you insert the following two lines of code:
NSString *test = [folderWindow name];
NSLog(@"Return value == %@; error message == %@", test, [[folderWindow lastError] localizedDescription]);
Then, Scripting Bridge tries to actually execute the name retrieval, fails, and comes back with a slightly-more-constructive error message:
Return value == (null); error message == The operation couldn’t be completed. (OSStatus error -1700.)
This is awesome (progress?!), but still doesn't get me a whole lot closer to solving the problem. That error message seems to indicate that there's an AEcoercion problem someplace, but I'm not sure how to proceed in solving it. The generated Finder.h file (and the Finder's AppleScript Dictionary) are both pretty clear about the fact that I should be getting back a reference to a FinderWindow object, and printing the folderWindow
object out seems to verify that everything is OK up until the name
call.
发布评论
评论(2)
它看起来像
-objectAtLocation:< /code>
需要一个
NSURL
而不是 HFS 样式的路径:我刚刚尝试了使用 NSURL 的代码,它工作正常。例如,以下代码
产生以下输出:
folder ==
(注意:我在创建 Finder.h 文件时使用了不同的参数(以防止容易混淆的名称,例如
FinderFinderWindow
),因此我的类名称会略有不同)。因此,您的代码应该可以工作,只要将其更改为以下内容:
更新:
不需要添加
-get
调用;get
是隐含的/可选的/多余的,就像在常规 AppleScript 中一样。我在尝试获取
[folderWindow iconViewOptions]
时收到无法识别的选择器
错误消息:-[SBObject iconViewOptions]:无法识别的选择器发送到实例0x10018e270
不过,您可以打印 FinderWindow 的属性:
生成如下内容:
It looks like
-objectAtLocation:
is expecting anNSURL
as opposed to an HFS-style path:I just tried code that used an NSURL and it worked okay. For example, the following code
produced the following output:
folder == <FinderFolder @0x482b00: FinderFolder
'furl'("file://localhost/Users/mdouma46/Desktop/") of application "Finder" (78829)>
(Note: I used different parameters when creating the Finder.h file (to prevent confusing names like
FinderFinderWindow
), so my class names will be slightly different).So, your code should probably work provided it's changed to the following:
UPDATED:
There should be no need for your added
-get
call;get
is implied/optional/superfluous just like in regular AppleScript.I'm getting an
unrecognized selector
error message when trying to get[folderWindow iconViewOptions]
:-[SBObject iconViewOptions]: unrecognized selector sent to instance 0x10018e270
You can print the properies of the FinderWindow though:
produces something like:
添加一些检查以确保
finder
、folderURL
和folderPathHFS
均有效。脚本桥可能会返回一个表示“无值”而不是 nil 的对象,并且该对象可能会返回另一个“无值”对象,因此您的任何检查都不会触发,因为它们都不为零,但是当您请求带有原始类型,返回0。Add some checks to make sure
finder
,folderURL
, andfolderPathHFS
are all valid. The scripting bridge may return an object representing "no value" instead of nil, and that object could return another "no value" object, so none of your checks will trigger because none of them are nil, but when you ask for something with a primitive type, it returns 0.