3

作成したオブジェクトがコントローラーのメソッドを呼び出してビューを更新できるように、ビュー コントローラーのインスタンス自体を渡すことで、ビュー コントローラーからクラスをインスタンス化することがあります。

それは常に、しばしば、または決して悪い習慣ですか?

具体的には:

ViewController.h は

-(void)updateButtonValue:(NSString*)value;

MyObject.h は

-(id)initWithViewController:(ViewController*)aViewController;

次のようにして、View Controller からそのクラスをインスタンス化します。

[[MyObject alloc] initWithViewController:self];

したがって、その MyObject インスタンスは、次のような単純な呼び出しでビューのボタン値を更新できます。

MyObject.m

[self.viewController updateButtonValue:@"example"];

必要以上に MyObject (ビュー コントローラー自体) を渡しているため、理想的とは思えませんが、確かに迅速で機能的です。プロトコルに依存するなど、より簡潔なアプローチがある場合は、簡単なコード サンプルを提供していただければ幸いです。

4

1 に答える 1

4

オブジェクトを密結合しているため、クラス型のポインターを渡すことは常に悪い習慣です (各オブジェクトは他のオブジェクトのクラスを知る必要があり、単一のオブジェクトである可能性もあります)。これがデリゲート パターンの目的です。MyObject が必要とする情報を最小限に抑えます (最小限、ポインター型にすぎません。idできれば、動作保証を提供するために MyObject によって指定されたプロトコルです)。

だからあなたの例を翻訳するには

MyObject.h

交換...

-(id)initWithViewController:(ViewController*)aViewController;

と...

-(id) init; 

(オーバーライドする理由が他にない場合は省略できます)

と...

@property (nonatomic, weak) id delegate;

myViewController でのインスタンス化 (する必要があります#include MyObject) ...

MyObject* object = [[MyObject alloc] init];

に続く

object.delegate = self;

(objectそれについて他に何も知る必要なく myViewController へのポインタを取得することに注意してください)

これで、内部からこれを行うことができますobject

 [self.delegate updateButtonValue:@"example"];

ただし...デリゲートがメッセージを確実に受信できるようにする必要がありますupdateButtonValue

これを行うには、このメソッドのシグネチャを使用して MyObject.h でプロトコルを宣言します。

@protocol MyObjectDelegate

  - (void) updateButtonValue:(NSString*)string;

@end

そして、viewController で、インターフェイス行で <> を使用して、このプロトコルに準拠していることを宣言します。

@interface ViewController <MyObjectDelegate>

(これは大したことではありません。ViewController は既に割り当て#include MyObject/初期化する必要があるため、これを行うためにこれ以上の情報は必要ありません)

そして、次のようにプロパティ宣言を展開します。

@property (nonatomic, weak) id <MyObjectDelegate> delegate

これで、コンパイラに十分な情報を与えて、準拠したメッセージのみを渡すことができるようにしました。ここで素晴らしいのは、MyObject は、デリゲート ポインターを介して到達する以外に、MyViewController について何も知る必要なく、自信を持ってメッセージを MyViewController に渡すことができるということです。

于 2013-02-14T03:21:45.363 に答える