1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
| import UIKit import RxSwift import RxCocoa
var mapping: [String: [Item]] = [:] var hasSwizzled = false let bag = DisposeBag()
public func track<T: UIViewController>(_ type: T.Type, selector: Selector? = nil, block: @escaping (T) -> Void) { let typeName = NSStringFromClass(type) if !hasSwizzled { let original = #selector(UIViewController.viewDidLoad) let swizled = #selector(UIViewController.trackers_viewDidLoad) swizzle(kClass: UIViewController.self, originalSelector: original, swizzledSelector: swizled) hasSwizzled = true }
let selector = selector ?? #selector(UIViewController.viewDidAppear(_:))
let item = Item(selector: selector, block: { (controller) in if let controller = controller as? T { block(controller) } })
if var items = mapping[typeName] { items.append(item) mapping[typeName] = items } else { mapping[typeName] = [item] } }
class Item { let selector: Selector let block: (UIViewController) -> Void
init(selector: Selector, block: @escaping (UIViewController) -> Void) { self.selector = selector self.block = block } }
extension UIViewController { func trackers_viewDidLoad() { trackers_viewDidLoad()
let typeName = NSStringFromClass(type(of: self)) let items = mapping[typeName] items?.forEach({ (item) in self .rx .sentMessage(item.selector) .subscribe(onNext: { _ in item.block(self) }, onCompleted: { print("completed") }) .disposed(by: bag) }) } }
func swizzle(kClass: AnyClass, originalSelector: Selector, swizzledSelector: Selector) { let originalMethod = class_getInstanceMethod(kClass, originalSelector) let swizzledMethod = class_getInstanceMethod(kClass, swizzledSelector)
let didAddMethod = class_addMethod(kClass, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))
if didAddMethod { class_replaceMethod(kClass, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)) } else { method_exchangeImplementations(originalMethod, swizzledMethod) } }
|