I want to have a listener
of sorts that reports whenever a new UIViewController is pushed. I can achieve this by subclassing from a single class and then listening in super viewDidLoad
/viewDidAppear
calls. But I would still have to pass the subclass name to super.
Is there any other way to automatically detect whenever any new view appears?
Context of it is that I am working on a logging
library that reports screen load time etc. I also want to listen to any button tap ever in the app at a single point.
For logging purposes, you don't need to subclass or tediously add code to every UIViewController instance. Instead, swizzle the UIViewController's viewDidAppear method with your own.
private let swizzling: (AnyClass, Selector, Selector) -> () = { forClass, originalSelector, swizzledSelector in
let originalMethod = class_getInstanceMethod(forClass, originalSelector)
let swizzledMethod = class_getInstanceMethod(forClass, swizzledSelector)
method_exchangeImplementations(originalMethod!, swizzledMethod!)
}
extension UIViewController {
static let classInit: Void = {
let originalSelector = #selector(viewDidAppear(_:))
let swizzledSelector = #selector(swizzledViewDidAppear(_:))
swizzling(UIViewController.self, originalSelector, swizzledSelector)
}()
@objc func swizzledViewDidAppear(_ animated: Bool) {
print("Add your logging logic here")
// Call the original viewDidAppear - using the swizzledViewDidAppear signature
swizzledViewDidAppear(animated)
}
}
Note you'll have to kick-off the swizzle by overriding the AppDelegate's init for Swift 4.
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
override init() {
super.init()
UIViewController.classInit
}
Original credits to @efremidze and @TikhonovAlexander
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With