实现canClose的最佳实践(withDelegate:shouldClose:contextInfo :)

时间:2018-03-18 00:24:47

标签: swift macos

我第一次尝试使用基于NSDocument的应用程序。 (Xcode 9.2,Swift 4,macOS 10.12 Sierra和Cocoa / AppKit)

我想知道实现关闭Document没有自动保存的正确方法。你能告诉我关闭NSDocument的最佳做法吗?

当用户尝试关闭文档时,将调用以下NSDocument方法。

canClose(withDelegate:shouldClose:contextInfo:)

我调试参数并找到followimng:

delegate = MyApp.Document
shouldCloseSelector = _something:didSomething:soContinue:
contextInfo = libsystem_blocks.dylib `_NSConcreteMallocBlock

显然这样的选择器不可用,所以我认为这可以在这里改变,如:

override func canClose(withDelegate delegate: Any,
                       shouldClose shouldCloseSelector: Selector?,
                       contextInfo: UnsafeMutableRawPointer?) {
    let delegate : Any = self
    let shouldCloseSelector : Selector = #selector(Document.document(_:shouldClose:contextInfo:))
    super.canClose(withDelegate: delegate, shouldClose: shouldCloseSelector, contextInfo: contextInfo)
}

@objc func document(_ document : NSDocument, shouldClose flag : Bool, 
                    contextInfo: UnsafeMutableRawPointer?) {
    if document === self, flag {
        self.cleanup() // my cleanup method
        self.close() // NSDocument.close()
    }
}

deinit {
    Swift.print(#function, #line)
}

它似乎有用,但我想这不是正确的方法,因为忽略了原始参数(Selector / contextInfo)。

1 个答案:

答案 0 :(得分:1)

更新

我找到了解决方案。我希望这会对某人有所帮助。

private var closingBlock : ((Bool) -> Void)? = nil

override func canClose(withDelegate delegate: Any,
                       shouldClose shouldCloseSelector: Selector?,
                       contextInfo: UnsafeMutableRawPointer?) {
    let obj : AnyObject = delegate as AnyObject
    let Class : AnyClass = object_getClass(delegate)!
    let method = class_getMethodImplementation(Class, shouldCloseSelector!)
    typealias signature =
        @convention(c) (AnyObject, Selector, AnyObject, Bool, UnsafeMutableRawPointer?) -> Void
    let function = unsafeBitCast(method, to: signature.self)

    self.closingBlock = {[unowned obj, shouldCloseSelector, contextInfo] (flag) -> Void in
        function(obj, shouldCloseSelector!, self, flag, contextInfo)
    }

    let delegate : Any = self
    let shouldCloseSelector : Selector = #selector(Document.document(_:shouldClose:contextInfo:))
    super.canClose(withDelegate: delegate, shouldClose: shouldCloseSelector, contextInfo: contextInfo)
}

@objc func document(_ document : NSDocument, shouldClose flag : Bool,
                    contextInfo: UnsafeMutableRawPointer?) {
    if flag {
        self.cleanup() // my cleanup method
    }

    self.closingBlock?(flag)
    self.closingBlock = nil
}

override func close() {
    Swift.print(#function, #line, #file)
    super.close()
}

deinit {
    Swift.print(#function, #line, #file)
}

参考信息

https://developer.apple.com/library/content/releasenotes/AppKit/RN-AppKitOlderNotes/

  

跟随委托的方法的覆盖者的建议:didSomethingSelector:contextInfo:Pattern

https://github.com/DouglasHeriot/canCloseDocumentWithDelegate/blob/master/canCloseDocumentWithDelegate/Document.swift

  

展示如何实现NSDocument方法-canCloseDocumentWithDelegate:shouldCloseSelector:contextInfo:使用Swift。必须使用Objective-C来执行NSInvocation。