I'm trying to add a service to the Finder's context menu using this class:
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()
}
}
The service is announced in info.plist as follows:
<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>
Finally I have turned on the service in System Preferences/Keyboard/Shortcuts. So I see the service and can call it. But all I get when calling it is
Cannot find service provider for selector handleServices:userData:error: or handleServices:: for service handleServices
Received same error (Swift 3.1). Tried all ways in this topic but nothing helped. Found a solution here
Changed code from this
to this
and it works.
Try creating aliases for variables in your method like so.
There are two problems in your code:
Objective-C messages are sent to the service provider, therefore the Swift method must be "Objective-C compatible". This can be achieved by subclassing
NSObject
, or by marking the method with the@objc
attribute.The service handler method has the signature
which is mapped to Swift as
So this would be a correct version (which worked in my test):
Some more remarks:
is "optional chaining" and checks if the
contains()
method could be called onpboard.types
, in other words it checks only ifpboard.types != nil
. What you probably want is to check ifpboard.types != nil
and thecontains()
method returnstrue
. This can be achieved with the "nil-coalescing operator"??
:Next,
is documented to return an optional array of
NSString
s, so you could unwrap and convert that to aString
array withFinally, assigning an error string (to the pointer provided by the caller) would be done with