在Finder上下文中建立服务

时间:2015-07-14 10:25:36

标签: swift service contextmenu finder

我正在尝试使用此类向Finder的上下文菜单添加服务:

public class Service {
  public func handleServices(pboard:NSPasteboard, userData:String, error:UnsafeMutableBufferPointer<String>) {  // not sure about the correct parameters
    if (pboard.types?.contains(NSFilenamesPboardType) != nil) {
      let fileArray = pboard.propertyListForType(NSFilenamesPboardType)
      print(fileArray)
    }
  }

  init () {
    NSApp.servicesProvider = self
    NSUpdateDynamicServices()
  }
}

该服务在info.plist中公布如下:

<key>NSServices</key>
<array>
    <dict>
        <key>NSMenuItem</key>
        <dict>
            <key>default</key>
            <string>Service Handling Demo</string>
        </dict>
        <key>NSMessage</key>
        <string>handleServices</string>
        <key>NSPortName</key>
        <string>services</string>
        <key>NSSendTypes</key>
        <array>
            <string>NSFilenamesPboardType</string>
        </array>
    </dict>
</array>

最后,我在“系统偏好设置”/“键盘/快捷方式”中打开了该服务。所以我看到了服务并且可以调用它。但是我在打电话时得到的只是

  

找不到选择器handleServices的服务提供者:userData:error:或handleServices :: for service handleServices

3 个答案:

答案 0 :(得分:5)

您的代码中存在两个问题:

  • Objective-C消息被发送到服务提供者,因此是Swift 方法必须是“Objective-C兼容”。这可以通过子类化来实现 NSObject,或使用@objc属性标记方法。

  • 服务处理程序方法具有签名

    - (void)handleServices:(NSPasteboard *)pboard
                  userData:(NSString *)userData
                     error:(NSString **)error
    

    映射到Swift为

    func handleServices(pboard: NSPasteboard!,
                      userData: String!,
                         error: AutoreleasingUnsafeMutablePointer<NSString?>)
    

所以这将是一个正确的版本(在我的测试中有效):

public class Service {

    @objc public func handleServices(pboard: NSPasteboard!,
        userData: String!, error: AutoreleasingUnsafeMutablePointer<NSString?>) {

        // ...
    }

    init() {
        NSApp.servicesProvider = self
        NSUpdateDynamicServices()
    }
}

更多评论:

if (pboard.types?.contains(NSFilenamesPboardType) != nil) { ... }

是“可选链接”并检查是否可以在contains()上调用pboard.types方法, 换句话说,它仅检查pboard.types != nil。你可能想要什么 是检查pboard.types != nil contains()方法是否返回true。 这可以通过“nil-coalescing operator”??

来实现
if (pboard.types?.contains(NSFilenamesPboardType) ?? false) { ... }

接下来,

pboard.propertyListForType(NSFilenamesPboardType)
记录

返回NSString的可选数组,因此您可以解包 并使用

将其转换为String数组
if let fileArray = pboard.propertyListForType(NSFilenamesPboardType) as? [String] { ... }

最后,指定一个错误字符串(指向由。提供的指针) 调用者)将完成

if (error != nil) {
    error.memory = "My error description"
}

答案 1 :(得分:2)

收到相同的错误(Swift 3.1)。尝试了这个主题的所有方法,但没有任何帮助。找到了解决方案here

从此

更改了代码
@objc public func handleServices(pboard: NSPasteboard!,
    userData: String!, error: AutoreleasingUnsafeMutablePointer<NSString?>) 

到这个

@objc public func handleServices(_ pboard: NSPasteboard,
 userData: String, error:AutoreleasingUnsafeMutablePointer<NSString>) 

它有效。

答案 2 :(得分:0)

尝试为方法中的变量创建别名,如此。

public func handleServices(pboard:NSPasteboard, userData userData:String, error error:UnsafeMutableBufferPointer<String>)