NSUndoManager приведение сбоя NSUndoManagerProxy в коде Swift
В нашем приложении мы используем следующий код:
let lInvocationTarget = lUndoManager.prepare(withInvocationTarget: self)
let _ = (lInvocationTarget as! MyObjectType).myMethod(_: self.opacity, undoManager: lUndoManager)
Он компилируется без предупреждений и работает нормально под macOS 10.12 Sierra. Однако он вылетает во время выполнения 10.9 - 10.11 (Маверикс до Эль-Капитана). Уведомление о сбое:
Не удалось преобразовать значение типа "NSUndoManagerProxy" (0x7fff76d6d9e8) в "MyObjectType" (0x108b82218).
Затем я переписал код:
if let lInvocationTarget = lUndoManager.prepare(withInvocationTarget: self) as? MyObjectType {
let _ = lInvocationTarget.setOpacity(_: self.opacity, undoManager: lUndoManager)
}
Тогда это не падает, но тогда Отмена вообще не работает. Этот последний способ написания взят непосредственно из документации Apple, поэтому, очевидно, поведение изменилось в Swift 3 или 10.12 SDK. Я использую Xcode 8.2 с Swift 3 и SDK 10.12
RegisterUndo(withTarget, selector:, object:) не подходит, потому что у меня есть много других отменяемых методов с большим количеством аргументов. На самом деле не хочу, чтобы обернуть их в словарь или так. И даже когда селекторы в настоящее время довольно безопасны, они все равно мне не нравятся. Существует также API на основе блоков (registerUndo(withTarget: handler:)), но это, к сожалению, только для 10.11+.
Кто-нибудь сталкивался с такой же проблемой? И еще важнее: кто-нибудь придумал выход?
2 ответа
Я так удивлен, что слышу, как ваш первый код работает на macOS 10.12. Метод prepare(withInvocationTarget:)
была вещь, которая вряд ли работает в Swift. Не только возвращаемый прокси-объект не является экземпляром исходного класса, но и не является потомком объекта. NSObject
(в аренде в некоторых бывших OS Xs).
В любом случае, это стоит попробовать
let lInvocationTarget = lUndoManager.prepare(withInvocationTarget: self)
_ = (lInvocationTarget as AnyObject).myMethod(self.opacity, undoManager: lUndoManager)
Я обнаружил, что registerUndoWithTarget:handler: сейчас лучший API.