2015-07-14 2 views
2

Я пытаюсь добавить службу в контекстном меню Finder, используя этот класс:создать службу в контексте Finder

public class Service { 
    public func handleServices(pboard:NSPasteboard, userData:String, error:UnsafeMutableBufferPointer<String>) { // not sure about the correct parameters 
    if (pboard.types?.contains(NSFilenamesPboardType) != nil) { 
     let fileArray = pboard.propertyListForType(NSFilenamesPboardType) 
     print(fileArray) 
    } 
    } 

    init() { 
    NSApp.servicesProvider = self 
    NSUpdateDynamicServices() 
    } 
} 

Услуга объявлена ​​в info.plist следующим образом:

<key>NSServices</key> 
<array> 
    <dict> 
     <key>NSMenuItem</key> 
     <dict> 
      <key>default</key> 
      <string>Service Handling Demo</string> 
     </dict> 
     <key>NSMessage</key> 
     <string>handleServices</string> 
     <key>NSPortName</key> 
     <string>services</string> 
     <key>NSSendTypes</key> 
     <array> 
      <string>NSFilenamesPboardType</string> 
     </array> 
    </dict> 
</array> 

Наконец, я включил службу в Системные настройки/Клавиатура/Ярлыки. Поэтому я вижу службу и могу ее назвать. Но все, что я получаю при вызове, это

Cannot find service provider for selector handleServices:userData:error: or handleServices:: for service handleServices

+0

My * guess * будет состоять в том, что класс должен наследовать от 'NSObject' (или помечен' @ objc'). –

+0

@MartinR к сожалению нет. Я попробовал и то, и другое. –

ответ

5

Есть две проблемы в вашем коде:

  • сообщения Objective-C отправляемые поставщика услуг, поэтому метод Swift должен быть "Objective-C совместимый". Это может быть достигнуто путем подкласса NSObject или путем маркировки метода атрибутом @objc.

  • Метод обработчика службы имеет подпись

    - (void)handleServices:(NSPasteboard *)pboard 
           userData:(NSString *)userData 
           error:(NSString **)error 
    

    , который сопоставлен Swift в

    func handleServices(pboard: NSPasteboard!, 
            userData: String!, 
            error: AutoreleasingUnsafeMutablePointer<NSString?>) 
    

Так это будет правильная версия (которая работала в моем тесте):

public class Service { 

    @objc public func handleServices(pboard: NSPasteboard!, 
     userData: String!, error: AutoreleasingUnsafeMutablePointer<NSString?>) { 

     // ... 
    } 

    init() { 
     NSApp.servicesProvider = self 
     NSUpdateDynamicServices() 
    } 
} 

Еще несколько замечаний:

if (pboard.types?.contains(NSFilenamesPboardType) != nil) { ... } 

является «факультативной цепочкой» и проверяет, является ли метод могут быть вызваны pboard.types, других словами он проверяет только если pboard.types != nil. Что вы, вероятно, хотите , чтобы проверить, pboard.types != nilи метод возвращает true. Это может быть достигнуто с «нулевой-коалесцирующим оператором» ??:

if (pboard.types?.contains(NSFilenamesPboardType) ?? false) { ... } 

Далее,

pboard.propertyListForType(NSFilenamesPboardType) 

документирован вернуть дополнительный массив NSString с, так что вы можете разворачивать и преобразовать его в String массив с

if let fileArray = pboard.propertyListForType(NSFilenamesPboardType) as? [String] { ... } 

Наконец, присваивая строку ошибки (в пуантах г обеспечивается вызывающего абонента) будет сделано с

if (error != nil) { 
    error.memory = "My error description" 
} 
+0

Я также сделал небольшой тест, и ваш код действительно работает :-) Большое спасибо! Есть еще одна проблема, если я запишу ее в свое «настоящее» приложение, где я до сих пор получаю сообщение «не найден», но я думаю, что найду это, сократив код. –

0

Попробуйте создать псевдонимы для переменных в вашем методе.

public func handleServices(pboard:NSPasteboard, userData userData:String, error error:UnsafeMutableBufferPointer<String>) 
+0

Почему? Что это решит? – Moritz

+0

Ну, это вызовет предупреждения компилятора: «Внешнее имя дублирующего параметра,« userData »уже имеет метку аргумента« –

+0

@ThomasKilian Точно. Хотя этот синтаксис может работать с Swift 2 ... (повторение имени параметра заменено с помощью '#' перед ним для создания внутренних именованных параметров), но я не вижу, как это могло бы помочь OP в любом случае. Мой комментарий был наполовину смехотворным наполовину реальным вопросом (будет ли это помогать OP или нет? Я думаю, что нет, но если s1ddok может рассказать нам, почему он думал, что этот ответ может помочь, я буду признателен и, может быть, что-нибудь узнаю). – Moritz

2

Received же ошибки (Swift 3.1).Пробовал все пути в этой теме, но ничего не помогло. Найдено решение here

Измененный код из этого

@objc public func handleServices(pboard: NSPasteboard!, 
    userData: String!, error: AutoreleasingUnsafeMutablePointer<NSString?>) 

к этому

@objc public func handleServices(_ pboard: NSPasteboard, 
userData: String, error:AutoreleasingUnsafeMutablePointer<NSString>) 

и она работает.