В моем приложении подкласса NSDocument
критически важная аппаратная часть - пользователи действительно не хотят закрывать документ случайно! Итак, я внедрил canCloseDocumentWithDelegate…
, чтобы показать NSAlert
и спросить перед закрытием.Как реализовать метод NSDocument -canCloseDocumentWithDelegate: shouldCloseSelector: contextInfo: в Swift?
Теперь я пытаюсь реализовать эту же вещь в приложении, написанном в Swift.
Поскольку ответ поступает асинхронно, результат «должен закрыть» передается обратному вызову делегата, а не просто возвращается. В документации к -canCloseDocumentWithDelegate:shouldCloseSelector:contextInfo:
, он говорит:
shouldCloseSelector метод обратного вызова должна иметь следующую подпись:
- (void)document:(NSDocument *)doc shouldClose:(BOOL)shouldClose contextInfo:(void *)contextInfo
Так что, как есть 3 аргументов различных типов, я не могу использовать простые методы performSelector:withObject:
- вам нужно использовать NSInvocation. Обратите внимание, что делегат имеет тип id
, а подпись выше не отображается в каком-либо формальном протоколе - вы не можете просто вызвать метод в обычном режиме. (См. Это mailing list post, например, как это должно быть сделано)
Теперь проблема заключается в том, что NSInvocation не разрешено в Swift! См. Swift blog “What Happened to NSMethodSignature”:
Привлечение каркасов Cocoa к Swift дало нам уникальную возможность взглянуть на наши API-интерфейсы с новой перспективой. Мы нашли классы, которые нам не нравились цели Swift, чаще всего из-за приоритета, который мы придаем безопасности. Например, некоторые классы, связанные с вызовом динамического метода, не отображаются в Swift, а именно
NSInvocation
иNSMethodSignature
.
Это звучит неплохо, но падает, когда простой API NSDocument
требует еще NSInvocation! Реальное решение этой проблемы было бы для Apple, чтобы представить новый API canCloseDocument…
, используя обратный вызов блока. Но пока это не произойдет, какое лучшее решение?
Я могу подтвердить это! Вот мой примерный код, теперь использующий эту чистую реализацию Swift: https://github.com/DouglasHeriot/canCloseDocumentWithDelegate/commit/d664efdccabd4c049b60a99f70a0dc3bb866299e – DouglasHeriot