Использование расширений для редактирования изображений в Yosemite в собственном приложении
В моем приложении OS X я хочу, чтобы пользователь мог редактировать изображения с соответствующими расширениями действий, установленными на его/ее Mac, например расширение разметки изображения, которое присутствует в Mail.app или TextEdit (для файлов RTFD с изображениями) - или инструмент восстановления Pixelmator, если он доступен. Насколько я помню, Apple объявляет на WWDC '14, для этого будет публичный 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
.
Ответы
Ответ 1
К сожалению, похоже, что Apple действительно предоставляет Action Extensions через NSTextView
в настоящее время.
В ОС X NSTextView играет центральную роль в представлении расширений для пользователей.
Это достигается путем создания 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];
}
}
![NSTextView displaying Extensions]()
(Обратите внимание, что вставка изображения как NSTextAttachmentCell
вызывает странный сбой - rdar://20333977)
Эта странная граница, о которой вы упоминаете, кажется, является средством выбора общего доступа, которое отображается при наведении на изображение в NSTextView
, но слегка затененной кнопкой.
![NSButton displaying private NSSharingServicePicker menu]()
Я наткнулся на ваше репо GitHub и внесли свой вклад в то, что я узнал об этом в этот запрос на растяжение.
Я сделал хакерское обходное решение, представив NSSharingServicePicker
, как описано в вашем вопросе, а затем удерживая его на NSSharingService
, возвращенном в sharingServicePicker:sharingServicesForItems:proposedSharingServices:
. Затем сами службы могут быть вызваны с помощью performWithItems:
, а данные возвращаются в sharingService:didShareItems:
.
Мой код доступен здесь.
Ответ 2
На самом деле, хакерство "стиль" и реализация 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]];
}