2017-09-26 12 views
0

新しいUIViewControllerがプッシュされるたびにレポートする種類のlistenerが必要です。 これを実現するには、単一のクラスからサブクラスを作成し、次にviewDidLoad/viewDidAppearというスーパーファンクションでリッスンします。しかし、私はまだsuperにサブクラス名を渡さなければなりません。アプリケーション全体でviewWillAppear呼び出しを検出するリスナーを作成したい

新しいビューが表示されたときに自動的に検出する方法はありますか?

私はloggingライブラリーでスクリーンローディング時間などを報告しています。私はまた、アプリケーション内の任意のボタンタップを一点で聴きたいと思っています。

答えて

0

ここでObservableパターンを使用することはどうですか?各ビュー・コントローラをセットアップして、そのライフ・サイクル・メソッドの変更についてアプレットに通知します。必要に応じて、これらの変更をファイルに記録することができます。

0

私が言ったように、最良のアプローチは、View Controllerをサブクラス化して、viewDidLoad/viewWillDisappearメソッドのロギング部分を行うことです。 の場合、目的を達成するために各サブクラスでスーパークラスにサブクラス名を渡す必要はありません。あなたがのviewDidLoad関数をオーバーライドし、サブクラス化されますのViewControllerで

:何あなたが代わりに行うことができますが、以下である

override func viewDidLoad() { 
    super.viewDidLoad() 

    NotificationCenter.default.post(name: Notification.Name(rawValue: "ViewDidLoad"), object: nil, userInfo: [ 
     "name": NSStringFromClass(type(of: self)) 
    ]) 
} 

これは、ユーザ情報オブジェクト内の対応するビューコントローラ名で通知を掲載します。 次に、この通知を中央の場所(AppDelegateなど)で購読してイベントを処理できます。

0

それほど簡単な実装では、すべてのビューコントローラをサブクラス化して、通知を使用して自動的にイベントをオブザーバに送信するか、シングルトンでメソッドを実行するだけです。

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

サブクラス化ができない場合は、ロギングのために一人ひとりのUIViewController

1

ViewWillAppearObservableクラスにコードを追加することができ、あなたはサブクラスまたはうんざりするほどおきの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) 
    } 

} 

あなたがキックオフするスウィズルをスウィフト4.

@UIApplicationMain 
class AppDelegate: UIResponder, UIApplicationDelegate { 

    override init() { 
     super.init() 
     UIViewController.classInit 
    } 

オリジナルクレジットが@efremidzeと@TikhonovAlexander

するためのAppDelegateのinitをオーバーライドしています注意してください
関連する問題