在 Finder 上下文中建立服务

Establish a service in Finder context

我正在尝试使用此 class:

向 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>

终于在系统Preferences/Keyboard/Shortcuts中开启了服务。所以我看到了服务并可以调用它。但是我调用它时得到的只是

Cannot find service provider for selector handleServices:userData:error: or handleServices:: for service handleServices

尝试像这样在您的方法中为变量创建别名。

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

你的代码有两个问题:

  • Objective-C 消息 被发送到服务提供商,因此 Swift 方法必须是 "Objective-C compatible"。这可以通过子类化来实现 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) { ... }

是 "optional chaining" 并检查是否可以在 pboard.types 上调用 contains() 方法, 换句话说,它只检查 pboard.types != nil。你可能想要什么 是检查 pboard.types != nil contains() 方法 returns true。 这可以通过 "nil-coalescing operator" ??:

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

接下来,

pboard.propertyListForType(NSFilenamesPboardType)

被记录为 return 一个可选的 NSString 数组,因此您可以解包 并将其转换为 String 数组

if let fileArray = pboard.propertyListForType(NSFilenamesPboardType) as? [String] { ... }

最后,分配一个错误字符串(给 来电者)将完成

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

收到相同的错误 (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>) 

而且有效。