2017-11-19 8 views
0

さまざまなタイプの多くの異なるView ControllerでviewWillAppearの認証チェックを実行する必要がありますが、毎回再入力する必要はありません。また、チェックを終了するには、viewWillDisappearに渡すハンドラ変数を追加する必要があります。ほとんどのviewWillAppear呼び出しで機能を実行

class ForumLanderViewController: UIViewController, AuthCheck {}

は、私は単純に(私は関数を実行する必要がフラグにAuthCheckを使用して)のようなものを含めることができるように拡張またはプロトコル(またはいくつかの他の方法)を介してこれを行うことができます私はその1つのプロパティを追加することができますので、クラス自体に変数を実装する必要はなく、このコントローラ用に自動的に実装されます。

拡張機能を使用して既存のクラスに新しい関数を追加するという考え方がありますが、viewWillAppearviewWillDisappearにどのようにフックして、特定のビューコントローラの変数を単純なDRY方法で渡しますか?

答えて

0

プロトコルを使用すると、すべての適合オブジェクトが持つメソッド/プロパティのセットを定義してみましょう。

プロトコルは、基本クラスにすでに存在するメソッドの動作を作成したいので、何も役に立たないでしょう、UIViewController

拡張機能を使用すると、オブジェクトにメソッドやプロパティを追加できます。オブジェクトを定義するファイルの外にある可能性があります。ただし、共通の基本クラスにそのコードを関連付ける場合を除き、複数のクラス間で拡張機能のコードを共有することはできません。

@Taierさんの回答では、viewWillAppearの実装を置き換えるためにメソッドスウィズルを使用することができますが、推奨しません。これは、Objective-CメッセージのディスパッチとObjective-Cランタイムの詳細に依存しています。これは、今後数年間で段階的に廃止されると思われます。

すべてのクラスを共通の基本クラスから継承させることができる場合は、その基本クラスにviewWillAppearのカスタムバージョンを作成することができます。

0

あなたはメソッドスウィズルhttp://nshipster.com/method-swizzling/

メソッドのスウィズリングを使用することができますが 既存のセレクタの実装を変更するプロセスです。これは、 ディスパッチテーブル内の基本関数にセレクタがどのようにマップされるのかを変更することによって、実行時に Objective-Cのメソッド呼び出しを変更することが可能になりました。

例えば、我々は、各ビュー コントローラはiOSアプリでユーザに提示された回数を追跡したいとしましょう:各ビューコントローラはviewDidAppearの独自の実装 にトラッキングコードを追加することができ

:,しかし、それは複製された大量のコードのためになるでしょう 定型文。サブクラス化は別の可能性もありますが、 では、UIViewController、UITableViewController、 UINavigationController、およびその他のすべてのView Controllerクラスをサブクラス化する必要があります。 アプローチではコードの重複が発生します。

幸運にも、別の方法があります:方法はカテゴリからうわさです。

は、ここでそれを行う方法は次のとおりです。

private let swizzling: (UIViewController.Type) ->() = { viewController in 

    let originalSelector = #selector(viewController.viewWillAppear(_:)) 
    let swizzledSelector = #selector(viewController.proj_viewWillAppear(animated:)) 

    let originalMethod = class_getInstanceMethod(viewController, originalSelector) 
    let swizzledMethod = class_getInstanceMethod(viewController, swizzledSelector) 

    method_exchangeImplementations(originalMethod, swizzledMethod) } 

extension UIViewController { 

    open override class func initialize() { 
     // make sure this isn't a subclass 
     guard self === UIViewController.self else { return } 
     swizzling(self) 
    } 

    // MARK: - Method Swizzling 

    func proj_viewWillAppear(animated: Bool) { 
     self.proj_viewWillAppear(animated: animated) 

     let viewControllerName = NSStringFromClass(type(of: self)) 
     print("viewWillAppear: \(viewControllerName)") 
    } 
} 
+1

これは技術的には正しいですが、私は特別な状況やあなたが何をしているのか本当に知っている場合を除いてはアドバイスしません。 1つは、メソッドSwizzlingはネイティブのSwift関数呼び出しでは機能しません.Objective-Cの動的メソッドディスパッチだけです。言語とOSが進化するにつれて、利用できなくなる可能性があります。 –

+0

私は応答を感謝しますが、私は@ダンカンCのアドバイスにも気をつけて、うねりを避けるつもりです。両方のおかげで! –

関連する問題