想要创建一个监听器来检测整个应用程序的viewWillAppear调用
我想要有一个listener
种类,每当推送新的UIViewController时就会报告。 我可以通过从一个班级继承,然后在超级viewDidLoad
/viewDidAppear
调用中实现此目的。但我仍然必须将子类名称传递给super。想要创建一个监听器来检测整个应用程序的viewWillAppear调用
是否有任何其他方式来自动检测任何新的视图出现?
上下文是,我正在研究一个logging
库,报告屏幕加载时间等。我也想听任何按钮在应用程序点击一个点。
如何在这里使用Observable模式?设置每个视图控制器以通知appdelegate关于其生命周期方法的更改。如果需要,您可以将这些更改记录到文件中。
我认为,正如你所提到的,最好的方法是在ViewDidLoad/viewWillDisappear方法中创建视图控制器的子类并执行日志记录部分。 但是,你不需要在每个子类上传递子类名到超级来实现你想要的。你可以做的,而不是为以下:
在视图控制器,你将继承,覆盖viewDidLoad中功能:
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.post(name: Notification.Name(rawValue: "ViewDidLoad"), object: nil, userInfo: [
"name": NSStringFromClass(type(of: self))
])
}
这将发布一个通知,在用户信息对象对应的视图控制器的名字。 然后,您可以在中心位置(例如AppDelegate)订阅此通知并处理事件。
一个不太漂亮的实现是将所有的视图控制器子类化,以便它们使用通知或简单地在单例中运行方法自动将事件发送给观察者。
class ViewLifeCycleObserver {
static let shared = ViewLifeCycleObserver()
private(set) var viewWillAppearControllerNames: [String] = []
private(set) var viewDidLoadControllerNames: [String] = []
private init(){
}
func viewDidLoad(inViewController viewController: UIViewController){
viewDidLoadControllerNames.append(viewController.className)
print(viewController.className)
}
func viewWillAppear(inViewController viewController: UIViewController){
viewWillAppearControllerNames.append(viewController.className)
print(viewController.className)
}
}
class ViewWillAppearObservable: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
ViewLifeCycleObserver.shared.viewDidLoad(inViewController: self)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
ViewLifeCycleObserver.shared.viewWillAppear(inViewController: self)
}
}
extension UIViewController {
var className: String {
return NSStringFromClass(self.classForCoder).components(separatedBy: ".").last!
}
}
如果子类是不是一种选择,你可以在ViewWillAppearObservable
类的代码添加到每个UIViewController的
进行日志记录,你不需要继承或繁琐代码添加到每一个的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)
}
}
注意你必须通过覆盖AppDelegate中的init的雨燕4
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
override init() {
super.init()
UIViewController.classInit
}
原始学分@efremidze开球的调酒和@TikhonovAlexander