【问题标题】:Open file in Finder window OSX在 Finder 窗口 OSX 中打开文件
【发布时间】:2014-08-19 14:14:23
【问题描述】:

我的问题是关于打开 Finder 窗口来显示文件。

要打开单个文件,可以这样做:

[[NSWorkspace sharedWorkspace] selectFile:file.path 
                 inFileViewerRootedAtPath:file.path];

现在,如果用户尝试打开相同的 file.path,我需要一个 Finder。

为了实现这一点,我在一个数组中添加了file.path

但是当用户关闭Finder 窗口并再次尝试打开文件时我被卡住了(因为活动窗口具有带有路径的数组)。然后Finder不显示:(

任何帮助如何进行此操作。


  1. 有没有办法检查Finder窗口打开的路径?

  2. 有没有办法为查找器获取回调,以便我可以从数组中删除file.path

【问题讨论】:

    标签: objective-c macos cocoa finder nsworkspace


    【解决方案1】:

    只需传递nil 即可完成。

    [[NSWorkspace sharedWorkspace] selectFile:file.path inFileViewerRootedAtPath:nil];
    

    现在即使多次点击也会选择相同的文件/文件夹。

    【讨论】:

    • 使用 Xcode 8.2.1 并针对 OSX 10.11 进行编译,需要将 nil 参数替换为 @"" 以抑制出现的 Null passed to callee that requires a non-null argument 警告。
    【解决方案2】:

    我的第一选择是在我的应用程序中创建类似窗口的 finder 并在其中打开文件,这样您就可以完全控制自己的操作。

    第二个选项可能是创建可编写脚本的可可应用程序。这可以提供您在问题中描述的功能,它也与沙盒兼容。来自苹果:Gatekeeper and Signing Applets

    以上链接的摘要。

    Gatekeeper 和签名小程序 OS X Mountain Lion 包括 Gatekeeper、 通过应用策略来保护用户免受恶意软件的侵害 关于允许运行哪些下载的软件。看门人依赖 代码签名以验证应用程序:签名的应用程序是 保证由签名者创建,并且没有被 自签署以来已修改。默认情况下,Gatekeeper 将允许 仅运行已由 Mac App Store 签名的应用程序 或已确定的开发人员。如果您编写脚本应用程序 (“小程序”)进行分发,则本政策适用于您的 小程序。签署您的小程序,以便 Gatekeeper 的默认策略不会 阻止他们:

    我们需要什么:

    1. 创建 *.sdef 文件,该文件定义应用程序的可脚本性信息。 Scriptability Information
    2. 为您的应用程序添加 Cocoa 脚本支持 Cocoa Support for Scriptable Applications
    3. 创建 Applescript 以打开“命名”的 Finder 窗口并将信息发送回您的 Cocoa 应用程序,反之亦然。
    4. 从您的应用中调用 Applescript,反之亦然。

    您需要创建 *.sdef 文件,它是一种基于 XML 的格式,描述了一组可脚本性术语以及描述应用程序可脚本性的命令、类、常量和其他信息。您需要将此文件添加到您的项目中。

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE dictionary SYSTEM "file://localhost/System/Library/DTDs/sdef.dtd">
    <dictionary title="YOUR_APP_NAME">
        <suite name="scriptTest Suite" code="MApN" description="YOUR_APP_NAME Scripts">
            <command name="myFirstCommand" code="lkpstrng" description="The array to lookup">
                <cocoa class="MyLookupCommand"/> 
                <direct-parameter description="The array to lookup">
                    <type type="any" list="yes"/>
                </direct-parameter>
                <result description="returns and array" type="text"/>
            </command>
        </suite>
    </dictionary>
    

    将 *.sdef 文件包含到您的项目中后,您需要向 info.plist 添加两个新键。 Scriptable = YES 和脚本定义文件名。

    在定义为MyLookupCommand的脚本定义文件cocoa class中,我们需要在Cocoa app中创建这个类。 MyLookupCommand 类是NSScriptCommand 的子类

    .h

    #import <Foundation/Foundation.h>
    @interface MyLookupCommand : NSScriptCommand
    @end
    

    .m

    #import "MyLookupCommand.h"
    
    @implementation MyLookupCommand
    
    -(id)performDefaultImplementation {
    
        // get the arguments
        NSDictionary *args = [self evaluatedArguments];
        NSString *stringToSearch = @"";
        if(args.count)
        {
            stringToSearch = [args valueForKey:@""];
        }
        else
        {
            //  error
            [self setScriptErrorNumber:-50];
            [self setScriptErrorString:@"Parameter Error......."];
        }
        // Implement your code logic
        [[NSNotificationCenter defaultCenter] postNotificationName:@"AppShouldLookupStringNotification" object:stringToSearch];
    
        return [NSString stringWithFormat:@"result: %@", [NSDate date]];
    }
    @end
    

    这就是您从 Applescript 捕获通信的方式。

    - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
    {
        [textbox1 setStringValue:[NSString stringWithFormat:@"%05d", 1]];
        [[NSNotificationCenter defaultCenter]
         addObserver:self
         selector:@selector(getValueFromScript:)
         name:@"AppShouldLookupStringNotification"
         object:nil];
    }
    
    -(void)getValueFromScript:(NSNotification *)notification
    {
        [yourTextbox setStringValue:[NSString stringWithFormat:@"from notification center %@", notification.object]];
    }
    

    下一步,我们需要一个 Applescript 来从 Cocoa 应用获取/设置命令。

    //In SDEF file we declared return type as array, here we created one.
    set groceryList to {"eggs", "milk", "bread"} //the variable which you want to send to your app.
    
    //Scripting language is pretty straight forward. If "named" window exists invoke the command and send return type to your Cocoa app.
    tell application "Finder"
        activate
        if ((count of windows) > 0) then
            if name of front window is "YOUR_DESIRED_FINDER_WINDOW_NAME" then
    
                tell application "System Events"
                    set running_apps to every application process's name
                    if running_apps does not contain "YOUR_COCOA_APP_NAME" then
                        tell application "AppleScript Editor" to activate
                    end if
                end tell
    
                tell application "AppleScript Editor"
                    if it is running then
                        tell application "AppleScript Editor"
                            myFirstCommand groceryList //Updated this line. 
                        end tell
                    end if
                end tell
    
            end if
        end if
    end tell
    

    当然,您还需要从您的 Cocoa 应用程序中调用 Applescript 小程序。请看How to call Applescript from cocoa App - regulus6633's answer

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-16
      • 2019-02-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多