Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Overriding at-objc methods defined in extensions without the dynamic keyword
// Paste this into an iOS playground in Xcode and run
// Expected output:
// ParentVC: handled in ParentCoordinator
// ChildVC: handled in ChildCoordinator
// UIViewController: accountLogin() not handled
import UIKit
NSSetUncaughtExceptionHandler { exception in
print("Exception: \(exception.name)\(exception)")
print("Call stack:\n\(exception.callStackSymbols.joined(separator: "\n"))")
}
extension UIResponder {
@objc var coordinatingResponder: UIResponder? {
return next
}
@objc /* no dynamic */ func accountLogin() -> String {
return coordinatingResponder?.accountLogin() ?? "\(#function) not handled"
}
}
class ParentCoordinator: UIResponder {
override func accountLogin() -> String {
return "handled in ParentCoordinator"
}
}
class ChildCoordinator: UIResponder {
override func accountLogin() -> String {
return "handled in ChildCoordinator"
}
}
class ParentVC: UIViewController {
let coordinator = ParentCoordinator()
let child = ChildVC(nibName: nil, bundle: nil)
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .yellow
view.addSubview(child.view)
child.view.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
child.view.topAnchor.constraint(equalTo: view.topAnchor, constant: 100),
child.view.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 100),
child.view.widthAnchor.constraint(equalToConstant: 200),
child.view.heightAnchor.constraint(equalToConstant: 200)])
addChild(child)
child.didMove(toParent: self)
}
override var coordinatingResponder: UIResponder? {
return coordinator
}
func didTapLogin() {
print("ParentVC:", accountLogin())
}
}
class ChildVC: UIViewController {
let coordinator = ChildCoordinator()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .green
}
override var coordinatingResponder: UIResponder? {
return coordinator
}
func didTapLogin() {
print("ChildVC:", accountLogin())
}
}
let parentVC = ParentVC(nibName: nil, bundle: nil)
import PlaygroundSupport
PlaygroundPage.current.liveView = parentVC
parentVC.didTapLogin()
parentVC.child.didTapLogin()
let uivc = UIViewController(nibName: nil, bundle: nil)
print("UIViewController:", uivc.accountLogin())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.