Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Image Editing extensions on Yosemite in own app

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 *)proposedServicesis 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 senderbutton.

like image 265
iljawascoding Avatar asked Feb 02 '15 21:02

iljawascoding


People also ask

How do I enable photo extensions on Mac?

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.


1 Answers

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];
    }
}

NSTextView displaying Extensions

(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.

NSButton displaying private NSSharingServicePicker menu

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 NSSharingServices 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.

like image 192
Josh Avatar answered Oct 17 '22 04:10

Josh