I was building an MVVM-C PoC and came up with this little thing to combine my controller delegate, responder chain, and UIApplicationDelegate/coordinator by testing for protocol conformance rather than function availability.
Has anyone else found success with this strategy, or if you haven't seen it before, what do you think?
// UIResponder+Target.swift
extension UIResponder {
func target<Type>(conformingTo type: Type.Type) -> Type? {
if let target = self as? Type {
return target
} else {
return next?.target(conformingTo: type)
}
}
func target<Type>(default value: Type?) -> Type? {
if let value = value {
return value
} else {
return next?.target(conformingTo: Type.self)
}
}
}
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
}
}
Seems like Apple fixed the nextResponder in iOS to go all the way to the app delegate. Do you have an equivalent of UIResponder.target(default:) to combine the delegate with the responder chain?