Yes, I do something similar. But since mine is for AppKit, it's somewhat more complicated. To mimic NSApplication
's target search strategy, I have to look at several objects not in the responder chain, and I have to search multiple possible responder chains in succession.
extension NSResponder {
public func nearestResponder<Target>(ofType type: Target.Type) -> Target? {
var app: NSApplication? = NSApplication.shared
var keyWindow = app!.keyWindow
var keyWindowController = keyWindow?.windowController
var mainWindow = app!.mainWindow
var mainWindowController = mainWindow?.windowController
if mainWindow === keyWindow { mainWindow = nil }
var next: NSResponder? = self
while let candidate = next {
if let match = candidate as? Target {
return match
}
if candidate === keyWindow {
if let match = keyWindow?.delegate as? Target { return match }
keyWindow = nil
}
if candidate === keyWindowController {
if let match = keyWindowController?.document as? Target { return match }
keyWindowController = nil
}
if candidate === mainWindow {
if let match = mainWindow?.delegate as? Target { return match }
mainWindow = nil
}
if candidate === mainWindowController {
if let match = mainWindowController?.document as? Target { return match }
mainWindowController = nil
}
if candidate === app {
if let match = app?.delegate as? Target { return match }
if let match = NSDocumentController.shared as? Target { return match }
app = nil
}
next = candidate.nextResponder ?? keyWindow.firstResponder ?? mainWindow.firstResponder ?? app
}
return nil
}
}