I am still recoding some stuff from Objective-C to Swift, and the thing that kept me awake is how to handle copy & paste in swift.
First things first, the Objective-C code looked as follows:
-(void)paste:(id)sender {
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
NSArray *classArray = [NSArray arrayWithObject:[NSString class]];
NSDictionary *options = [NSDictionary dictionary];
if ([pasteboard canReadObjectForClasses:classArray options:options])
{
NSArray *strings = [pasteboard readObjectsForClasses:classArray options:options];
[datasource cmdPaste:strings];
}
}
The first approach to convert this to Swift was straightforward:
func paste(sender: AnyObject?) {
let pasteboard = NSPasteboard.generalPasteboard()
if pasteboard.canReadObjectForClasses([NSPasteboardTypeString], options:nil) {
if let strings = pasteboard.readObjectsForClasses([NSPasteboardTypeString], options:nil) as? Array<String> {
dataSource.cmdPaste(strings)
}
}
}
However, while this code compiles fine, it does not work. At runtime it will throw exceptions about missing implementations for selectors:
-[__NSCFConstantString readableTypesForPasteboard:]: unrecognized selector sent to instance 0x7fff7729d5c0
I was unable to find something about this on the internet, seems I am the only one experiencing this problem!?! I tried several variations, but in the end I had to give up, nothing seemed to work. Sooner or later I would get the same message.
Next I tried to reuse the old Objective-C code, i.e. I introduced an Objective-C class that would read the strings from the pasteboard. Interestingly that did not work either !?! The same error would occur. But when I compiled and ran the old project (with the same version of Xcode) it would run without problems. Perhaps something in the runtime kernel? I don't know.
Since the Objective-C code was quite old, I tried another look at the documentation. But doing that with the old mind set did not yield any solution either. Until I hit upon the proper search string in google. There I found a blog entry that showed how to read a string from the pasteboard. And using that information I was also able to create a much more swifty way of handling the pasteboard:
func paste(sender: AnyObject?) {
let pasteboard = NSPasteboard.generalPasteboard()
if let nofElements = pasteboard.pasteboardItems?.count {
if nofElements > 0 {
// Assume they are strings
var strArr: Array<String> = []
for element in pasteboard.pasteboardItems! {
if let str = element.stringForType("public.utf8-plain-text") {
strArr.append(str)
}
}
// Exit if no string was read
if strArr.count == 0 { return }
// Perform the paste operation
dataSource.cmdPaste(strArr)
}
}
}
Happy coding
2015-06-17 Added more pboard and drag &drop stuff in this post
Did this help?, then please help out a small independent.
If you decide that you want to make a small donation, you can do so by clicking this
link: a cup of coffee ($2) or use the popup on the right hand side for different amounts.
Payments will be processed by PayPal, receiver will be sales at balancingrock dot nl
Bitcoins will be gladly accepted at: 1GacSREBxPy1yskLMc9de2nofNv2SNdwqH
We don't get the world we wish for... we get the world we pay for.
Thanks .max
ReplyDeleteI have not checked your answer, but it makes sense. Still, I now prefer the solution in the lower half of the post, which is also the way that Apple now seems to prefer.