objective-c - 在 10.6 下调用 Finder 的 Scripting Bridge 返回值不正确(但不会引发错误)

标签 objective-c cocoa macos applescript scripting-bridge

我一直在 StackOverflow 和其他地方浏览很多很多与 Scripting Bridge 相关的线程,但似乎无法在弄清楚为什么 Cocoa 代码块对 Finder 调用 Scripting Bridge 没有取得任何进展longer 在 10.6 下可以正常工作。 (类似版本的代码似乎在 10.5 下工作正常,我不知道是什么导致了行为的变化。)

基本上,我正在尝试访问 Finder 窗口的一些显示选项。我有以下代码块作为我的测试用例。我将它指向一个显示为图标的文件夹,当我运行代码时,没有错误 block 跳闸,但我总是在结束。

    // 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 相关的赋值语句的末尾时,我尝试打印出类名,但无济于事。

有什么想法吗?


更新

好的,所以我发现了上面代码中产生错误的位置,尽管我觉得我离解决问题还差得很远。事实证明,Scripting Bridge 的惰性评估掩盖了问题。如果在检索到对 FinderWindow 的引用后插入以下两行代码:

NSString *test = [文件夹窗口名称]; NSLog(@"返回值 == %@; 错误信息 == %@", test, [[folderWindow lastError] localizedDescription]);

然后,Scripting Bridge 尝试实际执行名称检索,但失败了,并返回一条更具建设性的错误消息:

返回值==(空);错误信息 == 操作无法完成。 (OSStatus 错误 -1700。)

这太棒了(进步?!),但仍然没有让我离解决问题更近一步。该错误消息似乎表明某处存在 AEcoercion 问题,但我不确定如何继续解决它。生成的 Finder.h 文件(和 Finder 的 AppleScript 字典)都非常清楚我应该取回对 FinderWindow 对象的引用,并且打印出 folderWindow 对象似乎可以验证这一点在 name 调用之前一切正常。

最佳答案

看起来像 -objectAtLocation: 期待一个 NSURL与 HFS 风格的路径相反:

"Discussion

This method is a generalization of objectAtIndex: for applications where the "index" is not simply an integer. For example, Finder can specify objects using a NSURL object as a location. In OSA this is known as "absolute position," a generalization of the notion of “index” in Foundation—it could be an integer, but it doesn't have to be. A single object may even have a number of different "absolute position" values depending on the container."

我刚刚尝试了使用 NSURL 的代码,它工作正常。比如下面的代码

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    MDFinderApplication *finder = [SBApplication 
            applicationWithBundleIdentifier:@"com.apple.finder"];

    NSURL *URL = [NSURL fileURLWithPath:[@"~/Desktop" stringByStandardizingPath]];
    if (URL) {
         MDFinderFolder *folder = [[finder folders] objectAtLocation:URL];
         NSLog(@"folder == %@", folder);
    }
}

产生了以下输出:

folder == <FinderFolder @0x482b00: FinderFolder 'furl'("file://localhost/Users/mdouma46/Desktop/") of application "Finder" (78829)>

(注意:我在创建 Finder.h 文件时使用了不同的参数(以防止混淆名称,如 FinderFinderWindow ),所以我的类名会略有不同)。

因此,如果将代码更改为以下内容,您的代码应该可以正常工作:

// Set up the Scripting Bridge
FinderApplication *finder = [SBApplication 
      applicationWithBundleIdentifier:@"com.apple.finder"];

// (folderPath is an NSString * containing a POSIX-style path to a folder)
NSURL *folderURL = [NSURL fileURLWithPath:folderPath];

// Get the Finder-native folder reference
FinderFolder* folder = [[finder folders] objectAtLocation:folderURL];
if (folder == nil) {
    NSLog(@"folder error: %@", [[folder lastError] localizedDescription]);
    return;
}

// Get the Finder-native container window associated with the folder
[folder reveal];
FinderFinderWindow *folderWindow = [folder containerWindow];
if (folderWindow == nil) {
    NSLog(@"folderWindow error: %@", [[folderWindow lastError] localizedDescription]);
    return;
}

// Retrieve the view preferences for the folder
// UPDATED: THE FOLLOWING WILL CAUSE AN "unrecognized selector":
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");
}

更新: 应该不需要你添加 -get称呼; get就像在常规 AppleScript 中一样是隐含的/可选的/多余的。

我得到一个 unrecognized selector尝试获取时出现错误消息 [folderWindow iconViewOptions] :

-[SBObject iconViewOptions]: unrecognized selector sent to instance 0x10018e270

虽然您可以打印 FinderWindow 的属性:

NSLog(@"properties == %@", [finderWindow properties]);

产生类似的东西:

properties == {
bounds = "NSRect: {{173, 289}, {1241, 663}}";
closeable = 1;
collapsed = 0;
columnViewOptions = "<SBObject @0x1fc5d010: columnViewOptions of
     FinderFinderWindow id 5696 of application \"Finder\" (78829)>";
currentView = "<NSAppleEventDescriptor: 'clvw'>";
floating = 0;
iconViewOptions = "<SBObject @0x1fc5d550: iconViewOptions of
    FinderFinderWindow id 5696 of application \"Finder\" (78829)>";
id = 5696;
index = 2;
listViewOptions = "<SBObject @0x1fc5cca0: listViewOptions of 
    FinderFinderWindow id 5696 of application \"Finder\" (78829)>";
modal = 0;
name = Applications;
objectClass = "<NSAppleEventDescriptor: 'brow'>";
position = "NSPoint: {173, 289}";
resizable = 1;
sidebarWidth = 0;
statusbarVisible = 1;
target = "<FinderFolder @0x1fc5db10: FinderFolder \"Applications\"
     of startupDisk of application \"Finder\" (78829)>";
titled = 1;
toolbarVisible = 1;
visible = 1;
zoomable = 1;
zoomed = 0;
}

关于objective-c - 在 10.6 下调用 Finder 的 Scripting Bridge 返回值不正确(但不会引发错误),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5507711/

相关文章:

ios - 如何知道文件正在通过 NSFileManager 写入

objective-c - 判断音频文件是否为VBR

XCode 使用 ncurses 构建命令行工具

xcode - 如何使用 Xcode 和 swift 2 对显示图形对象进行编码 - 表示 OS X 程序中字符串子字符串的箭头

macos - 安装时忽略 productbuild 路径

iphone - UISegmentedControl 选定索引始终为 0?

objective-c - 为协议(protocol)方法键入编码字符串

iphone - 如何使用 UITextRange 从 UITextField 获取子字符串

cocoa - AppKit 中的固定间距数字

macos - 如何在 OS X 中通过命令行获取事件用户的名称?