厳密に型指定されたオブザーバーパターン、またはObjective-C ++が必要な理由



「Objective-Cでのイベント処理」、イベントの委任(たとえば、 viewWillAppear:(BOOL)animated )、プログラムのさまざまな場所で同時に聴く必要がある場合の不便さについて、多くのコピーが既に壊れています。

Observerテンプレートの実装を提供したいと思います。これは、C ++ 0xの能力を使用し、次のように、厳密に型指定されたパラメーターのリストを使用して信号を宣言できます。
new TLSignal<NSString *, BOOL>(self); 

なぜなら 私のC ++に関する知識はかなり乏しいため、このコードを改善するためのアドバイスに感謝します。

猫の下で興味を持ってください。

問題の本質


多くの場合、イベントについて他のオブジェクトに通知する必要がある場合があります(プロパティの変更、状態の変更など)。一方、複数のリスナーが同時にイベントを受信できるように、1対多の対応を監視できる必要があります。 このため、デリゲート付きのオプションはすぐに消えます。
組み込みのObjective-Cツールにはどのようなオプションがありますか?
  1. 通知センター -もちろん、NCには独自の適用分野がありますが、プログラム全体のグローバルイベントにより適しています。イベントは文字列識別子によって識別されますが、これは良くありません。 さて、そのようなソリューションのパフォーマンスは、APIと同様に貧弱です。
  2. Key-Value Observing(KVO)は、オブジェクトのプロパティが変更されたときのイベントの特殊なケースです。 Bindingsのような素晴らしいことを実行できますが、APIはその魅力をすべて無効にします。


オブザーバーパターン


Wikipediaの記事よりも詳しく説明できないと思うので、詳細のみを明確にします。



したがって、シグナル宣言は次のようになります。
  new TLSignal<NSString *, BOOL>(self); 

つまり:


この場合、このイベントをリッスンするブロックは次のようになります。
 auto observerBlock = ^(id target, NSString *stringParam, BOOL boolParam) { NSLog(@"%@ %@ %d", target, stringParam, boolParam); }; 

最初のパラメーターIDターゲットに注意してください。これは常に送信され、この信号の「ホルダー」に等しくなります。

使用例


使用例のないコードはコードではないので、プログラムの小さな例を挙げたいと思います。その例では、信号の利点とその使用方法を示したいと思います。

ExampleViewController.h

 #import <UIKit/UIKit.h> #import "Signals.h" @interface ExampleViewController : UIViewController @property (nonatomic, readonly) TLSignal<UIView *> *viewDidLoadSignal; @end 

ここではすべてが簡単です。識別子viewDidLoadSignalを使用してシグナルを宣言します。これにより、UIViewインスタンスがリスナーに渡されます。

ExampleViewController.mm

 #import "ExampleViewController.h" @implementation ExampleViewController @synthesize viewDidLoadSignal = _viewDidLoadSignal; -(TLSignal<UIView *> *)viewDidLoadSignal { if(!_viewDidLoadSignal) { //             ( ) _viewDidLoadSignal = new TLSignal<UIView *>(self); } return _viewDidLoadSignal; } -(void)viewDidLoad { [super viewDidLoad]; //   ,     UIView self.viewDidLoadSignal->notify(self.view); } @end 


Appdelegate.mm

 #import "AppDelegate.h" #import "ExampleViewController.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)options { UIWindow window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; self.viewController = [[ExampleViewController alloc] initWithNibName:@"ViewController" bundle:nil]; //   ,         UIView self.viewController.viewDidLoadSignal->addObserver(^(TLSignal<UIView *> *signal, UIView *targetView) { targetView.backgroundColor = [UIColor blackColor]; }); self.window.rootViewController = self.viewController; [self.window makeKeyAndVisible]; return YES; } @end 


信号が使用されるコードのファイル拡張子は、.mではなく.mmでなければならないことに注意してください。そうしないと、通常のObjective-Cコードとして認識され、プラスの魔法を理解できません。

おわりに


Objective-C(たとえば2.5または3.0)で類似したものが標準レベルで表示されることを心から願っています。これが起こるまで、ライブラリを使用することをお勧めします(非常に使いやすく、小さなコードでも明確です私が持っているC ++の知識:)):
GitHubのTLSignals

先日、Cocoapodsに表示されます。これが発生するまで、 TLSignals.hファイルをプロジェクトにコピーして、作業を開始できます。

コードはテストで部分的にカバーされています。テストを読むと、その仕組みをよりよく理解できます。
GitHubのTLSignalsTests.mm

追加と改善に感謝するだけでなく、C ++の側面から弱点で鼻を突くだけでなく、一般的には、私たち全員が学んでいるだけなので;)

誤字や文法上の誤りが見つかった場合は、コメントが乱雑にならないように、それらについて個人的なメッセージに書いてください。

ご清聴ありがとうございました!

関連リンク


Source: https://habr.com/ru/post/J162235/


All Articles