I am trying to build a standalone system service (app with .service extension, saved to ~/Library/Services/) to replace user-selected text in Mac OS X.
I want to build it with Xcode and not Automator, because I am more accustomed to Objective-C than Applescript.
I found several examples on the internet, e.g. this and also Apple's documentation. I got the Xcode project appropriately configured and building without problems. However, when I install my service and try to use it, nothing happens.
The service method itself is executed: I placed code to show an NSAlert inside its method body and it shows. However, the selected text does not get replaced.
Any idea what might be missing? This is the method that implements the service:
- (void) fixPath:(NSPasteboard*) pboard
userData:(NSString*) userData
error:(NSString**) error
{
// Make sure the pasteboard contains a string.
if (![pboard canReadObjectForClasses:@[[NSString class]] options:@{}])
{
*error = NSLocalizedString(@"Error: the pasteboard doesn't contain a string.", nil);
return;
}
NSString* pasteboardString = [pboard stringForType:NSPasteboardTypeString];
//NSAlert* alert = [[NSAlert alloc] init];
//[alert setMessageText:@"WORKING!"];
//[alert runModal];
// ^ This alert is displayed when selecting the service in the context menu
pasteboardString = @"NEW TEXT";
NSArray* types = [NSArray arrayWithObject:NSStringPboardType];
[pboard clearContents];
[pboard declareTypes:types owner:nil];
// Set new text:
[pboard writeObjects:[NSArray arrayWithObject:pasteboardString]];
// Alternatively:
[pboard setString:pasteboardString forType:NSStringPboardType];
// (neither works)
return;
}
After careful reading of Apple's documentation, I found the answer: My service app's plist file was missing a key under the Services section:
I only had the opposite
NSSendTypes
key, which lets you send data from the client app to the service. This one is needed to send the modified text back (in the other direction).It is weird because, Apple's documentation seems to imply that specifying these two is no longer necessary since 10.6 (Snow Leopard).
For (hopefully) useful console spew, in terminal type:
defaults write -g ViewBridgeLogging -bool YES
Note: useful for services and extensions also.