想要创建一个侦听器来检测整个应用程序中的viewWillAppear调用

fri*_*cat 2 delegates objective-c ios swift

我想listener每当推送一个新的UIViewController时都报告一种。我可以通过从单个类中进行子类化,然后在super viewDidLoad/ viewDidAppear调用中进行侦听来实现此目的。但是我仍然必须将子类名称传递给super。

是否有其他方法可以自动检测到何时出现新视图?

上下文是我正在一个logging报告屏幕加载时间等的库中工作。我也想听应用程序中任何一次单击的按钮。

Jal*_*koo 7

出于日志记录的目的,您无需为每个UIViewController实例继承类或繁琐地添加代码。而是使用您自己的UIViewController的viewDidAppear方法。

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)
    }

}
Run Code Online (Sandbox Code Playgroud)

请注意,您必须通过覆盖Swift 4的AppDelegate的init来启动麻烦。

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    override init() {
        super.init()
        UIViewController.classInit
    }
Run Code Online (Sandbox Code Playgroud)

@efremidze和@TikhonovAlexander的原始积分

  • swizzling 确实很危险,应该非常小心地使用......仅适用于完全理解其含义的专业人士,而不仅仅是复制粘贴答案给新手开发人员。 (2认同)

Rak*_*ish 0

在这里使用 Observable 模式怎么样?设置每个视图控制器以通知 appdelegate 有关其生命周期方法的更改。如果需要,您可以将这些更改记录到文件中。