简体   繁体   English

当用户在 iOS 中导航屏幕时,如何跟踪当前可见 ViewController 的变化?

[英]How to track changes in currently visible ViewController as user navigating the screens in iOS?

I'm trying to replicate Firebase Analytics behaviour, which automatically fire screen events whenever ViewController screen get's changed with another.我正在尝试复制 Firebase 分析行为,它会在 ViewController 屏幕发生变化时自动触发屏幕事件。 Though I'm able to find currently visible ViewController using:虽然我可以使用以下方法找到当前可见的 ViewController:

UIApplication.shared.windows.first?.rootViewController?.presentedViewController UIApplication.shared.windows.first?.rootViewController?.presentedViewController

But I need some way to get notified for any change in rootViewController.但是我需要一些方法来获得有关 rootViewController 任何更改的通知。 I tried to observe this rootViewController using KVO, but I don't get any callback.我尝试使用 KVO 观察这个rootViewController ,但我没有得到任何回调。 I found that KVO only works on NSObject with dynamic properties.我发现 KVO 仅适用于具有动态属性的 NSObject。 Is there any way I could receive callback for change in ViewController?有什么方法可以接收 ViewController 更改的回调? Since this will be a library project, I couldn't make changes in main code to support the feature.由于这将是一个库项目,因此我无法更改主代码以支持该功能。

Following solution worked for me:-以下解决方案对我有用:-

import Foundation
import UIKit

public extension UIViewController {

@objc dynamic func _tracked_viewWillAppear(_ animated: Bool) {
    UserActivityTracker.startTracking(viewController: self)
}

static func swizzle() {
        //Make sure This isn't a subclass of UIViewController,
        //So that It applies to all UIViewController childs
        if self != UIViewController.self {
            return
        }
        let _: () = {
            let originalSelector =
                #selector(UIViewController.viewWillAppear(_:))
            let swizzledSelector =
                #selector(UIViewController._tracked_viewWillAppear(_:))
            let originalMethod =
                class_getInstanceMethod(self, originalSelector)
            let swizzledMethod =
                class_getInstanceMethod(self, swizzledSelector)
            method_exchangeImplementations(originalMethod!, swizzledMethod!);
        }()
    }
 } 

In above code _tracked_viewWillAppear() is my custom function which I want to call my implementation before actual implementation called.在上面的代码中 _tracked_viewWillAppear() 是我的自定义 function ,我想在调用实际实现之前调用我的实现。 Then in AppDeligate class, call UIViewController.swizzle() method, as follows:-然后在AppDeligate class中,调用UIViewController.swizzle()方法,如下:-

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.
    UIViewController.swizzle()
    return true
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM