Skip to content

Instantly share code, notes, and snippets.

@jeanetienne
Last active May 30, 2018 07:31
Show Gist options
  • Save jeanetienne/a63f21618d8f073d99e2b9d81edc3a5c to your computer and use it in GitHub Desktop.
Save jeanetienne/a63f21618d8f073d99e2b9d81edc3a5c to your computer and use it in GitHub Desktop.
//
// Logic necessary to implement a "closing handler" for a NSDocument
//
// This is inspired by:
// - https://stackoverflow.com/questions/49343307/best-practice-to-implement-canclosewithdelegateshouldclosecontextinfo
// - https://github.com/keith/radars/blob/master/NSDocumentSwiftAnnotations/NSDocumentSwiftAnnotations/Document.swift
// Keith's supporting documentation for his radar submission: http://www.openradar.me/33422662
// Documentation:
// - https://developer.apple.com/library/content/releasenotes/AppKit/RN-AppKitOlderNotes/
// Paragraph called: "Advice for Overriders of Methods that Follow the delegate:didSomethingSelector:contextInfo: Pattern"
//
// I'm not even sure I understand all that's happening here, use it at you own risk!
//
class MyDocument: NSDocument {
private var originalShouldCloseSelectorBlock : ((Bool) -> Void)? = nil
override func canClose(withDelegate delegate: Any, shouldClose shouldCloseSelector: Selector?, contextInfo: UnsafeMutableRawPointer?) {
guard let selector = shouldCloseSelector, let context = contextInfo,
let object = delegate as? NSObject, let objcClass = objc_getClass(object.className) as? AnyClass,
let method = class_getMethodImplementation(objcClass, selector) else {
super.canClose(withDelegate: delegate, shouldClose: shouldCloseSelector, contextInfo: contextInfo)
return
}
typealias FunctionSignature = @convention(c) (AnyObject, Selector, AnyObject, Bool, UnsafeMutableRawPointer?) -> Void
let function = unsafeBitCast(method, to: FunctionSignature.self)
self.originalShouldCloseSelectorBlock = {[unowned object, selector, context] (flag) -> Void in
function(object, selector, self, flag, context)
}
let delegate: Any = self
let shouldCloseSelector: Selector = #selector(document(_:shouldClose:contextInfo:))
super.canClose(withDelegate: delegate, shouldClose: shouldCloseSelector, contextInfo: contextInfo)
}
@objc func document(_ document: NSDocument, shouldClose: Bool, contextInfo: UnsafeMutableRawPointer?) {
//
// This is where you can do you own document-closing related logic
//
self.originalShouldCloseSelectorBlock?(shouldClose)
self.originalShouldCloseSelectorBlock = nil
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment