在自己的应用中使用 Yosemite 上的图像编辑扩展

Using Image Editing extensions on Yosemite in own app

在我的 OS X 应用程序中,我想让用户使用 his/her Mac 上安装的适当操作扩展来编辑图像,例如图像标记扩展 [= =28=] 或 TextEdit(用于带图像的 RTFD 文件)- 或 Pixelmator 的修复工具(如果可用)。据我所知,Apple 在 WWDC '14 上宣布将有一个 public API 用于此任务。

不幸的是,无论是文档还是示例代码,我都找不到关于如何从主机应用程序角度使用扩展的任何起点。

我发现您必须将 NSSharingPicker 的未记录样式 属性 设置为非零值,如下所示:

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

设置样式值后,您就知道自己走对了路,因为 - (NSArray *)sharingServicePicker:(NSSharingServicePicker *)sharingServicePicker sharingServicesForItems:(NSArray *)items proposedSharingServices:(NSArray *)proposedServices 是使用我系统上安装的图像编辑扩展程序调用的,而不是常规的共享扩展程序。

您还需要实现一个未记录的委托方法:

- (BOOL)sharingServicePicker:(NSSharingServicePicker *)sharingService shouldShowForView:(NSView*) inView
{
    return YES;
}

但是,选择器仍然没有出现。我得到的只是 sender 按钮周围的一些奇怪的边框。

不幸的是,Apple 目前似乎只通过 NSTextView 公开 Action Extensions。

On OS X, NSTextView plays the central role in presenting Extensions to the users.

这可以通过创建 NSTextView 并将图像作为 NSFileWrapper 插入其中来实现,例如(此代码改编自 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];
    }
}

(请注意,将图像作为 NSTextAttachmentCell 插入会导致奇怪的崩溃 – rdar://20333977

您提到的那个奇怪的边框似乎是 NSTextView 中将鼠标悬停在图像上时显示的共享服务选择器,但是被按钮稍微遮住了。

我偶然发现了 your GitHub repo and have contributed what I've learnt about it in this pull request

我通过按照您的问题中的描述提供 NSSharingServicePicker,然后保留 sharingServicePicker:sharingServicesForItems:proposedSharingServices: 中返回的 NSSharingService,实现了一个棘手的解决方法。然后可以使用 performWithItems: 调用服务本身,并在 sharingService:didShareItems:.

中返回数据

我的代码可用 here

其实,hacking "style" 属性和实现NSSharingServicePickerDelegate是不必要的,下面的代码更合适(当然,你应该实现NSSharingServiceDelegate协议):

- (IBAction)onServiceBtnClick:(id)sender {
NSURL *url = [self.quickLookItems firstObject];
NSImage *image = [[NSImage alloc] initWithContentsOfURL:url];
if (image) {
    self.serviceBtn.hidden = YES;

    NSMenu *menu = [[NSMenu alloc] initWithTitle:@"Sharing"];

    NSSharingService *service = [NSSharingService sharingServiceNamed:@"com.apple.Preview.Markup"];
    service.delegate = self;
    self.markupService = service;
    NSArray *services = @[ service ];

    for (NSSharingService *service in services) {
        NSMenuItem *menuItem = [[NSMenuItem alloc] initWithTitle:service.title action:@selector(share:) keyEquivalent:@""];
        [menu addItem:menuItem];
    }

    [menu popUpMenuPositioningItem:nil atLocation:[NSEvent mouseLocation] inView:nil];


    }
}

- (void)share:(NSMenuItem *)sender{
     NSURL *imageURL = [self.quickLookItems firstObject];
     [self.markupService performWithItems:@[imageURL]];
 }