In my OS X app, I want to let the user edit images with the appropriate action extensions installed on his/her Mac, e.g the image markup extension as present in Mail.app or TextEdit (for RTFD files with images) - or Pixelmator's repair tool if available. As far as I can recall, Apple announces at WWDC '14 there would be a public API for this task.
Unfortunately I cannot find any starting point on how to use extensions from a host app perspective, neither documentation- nor sample-code-wise.
I found out that you have to set the undocumented style property of the NSSharingPicker to a non-zero value like this:
- (IBAction)testSharingPicker:(id)sender
{
NSSharingServicePicker *picker = [[NSSharingServicePicker alloc] initWithItems:@[[self.listing.images.firstObject thumbImage]]];
[picker setValue:@(1) forKey:@"style"];
[picker setDelegate:self];
[picker showRelativeToRect:[sender bounds] ofView:sender preferredEdge:NSMinYEdge];
}
Once the style value is set, you know you are on the right track, because - (NSArray *)sharingServicePicker:(NSSharingServicePicker *)sharingServicePicker sharingServicesForItems:(NSArray *)items proposedSharingServices:(NSArray *)proposedServices
is called with the image editing extensions installed on my system, instead of the regular sharing extensions.
You also need to implement an undocumented delegate method:
- (BOOL)sharingServicePicker:(NSSharingServicePicker *)sharingService shouldShowForView:(NSView*) inView
{
return YES;
}
But still, the picker is not showing up. All I get is some weird border around the sender
button.
Turn on or off extensions on your Mac Choose Apple menu > System Preferences, then click Extensions. Click Photos Editing in the left sidebar. Your apps that include Photos extensions appear. Turn on the extensions that you want to use in Photos.
Unfortunately, it seems Apple only really exposes Action Extensions through NSTextView
at the present time.
On OS X, NSTextView plays the central role in presenting Extensions to the users.
That is achievable by creating a NSTextView
and inserting an image into it as a NSFileWrapper
, for example (this code adapted from TextEdit):
NSMutableAttributedString *attachments = [[NSMutableAttributedString alloc] init];
NSError *error;
NSFileWrapper *wrapper = [[NSFileWrapper alloc] initWithURL:[NSURL fileURLWithPath:@"/Users/user/Downloads/Test.png"] options:NSFileWrapperReadingImmediate error:&error];
if (wrapper) {
NSTextAttachment *attachment = [[NSTextAttachment alloc] initWithFileWrapper:wrapper];
[attachments appendAttributedString:[NSAttributedString attributedStringWithAttachment:attachment]];
}
if ([attachments length] > 0) {
NSRange selectionRange = [self.textView selectedRange];
if ([self.textView shouldChangeTextInRange:selectionRange replacementString:[attachments string]]) {
[[self.textView textStorage] replaceCharactersInRange:selectionRange withAttributedString:attachments];
[self.textView didChangeText];
}
}
(Note that inserting an image as a NSTextAttachmentCell
causes a weird crash – rdar://20333977)
That weird border you mention seems to be the Sharing Service Picker that's shown when hovering over an image in a NSTextView
, however obscured slightly by the button.
I stumbled on your GitHub repo and have contributed what I've learnt about it in this pull request.
I've achieved a hacky workaround by presenting the NSSharingServicePicker
as described in your question and then holding onto the NSSharingService
s returned in sharingServicePicker:sharingServicesForItems:proposedSharingServices:
. The services themselves can then be invoked with performWithItems:
and data is returned in sharingService:didShareItems:
.
My code is available here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With