5

たとえば、ビュー コントローラーの init メソッドでブロックを完了ハンドラーとして使用して、カスタムの initWithNibName:andResourceBundle:andThis:andThat: を作成しなくても、親ビュー コントローラーがブロックの詳細を入力できるようにすることは可能ですか?可能なプロパティごとに?

// ... in the didSelectRowAtIndexPath method of the main view controller :
SubViewController *subviewController = [[SubViewController alloc] initWithNibName:nil bundle:nil completionHandler:^(SubViewController * vc) {
    vc.property1 = NO;
    vc.property2 = [NSArray array];
    vc.property3 = SomeEnumValue;
    vc.delegate = self;
}];
[self.navigationController pushViewController:subviewController animated:YES];
[subviewController release];

SubViewController.m で:

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil completionHandler:(void (^)(id newObj))block {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        block(self);
    }
    return self;
}

それ以外の

// ... in the didSelectRowAtIndexPath method of the main view controller :
SubViewController *subviewController = [[SubViewController alloc] initWithNibName:nil bundle:nil andProperty1:NO andProperty2:[NSArray array] andProperty3:SomeEnumValue andDelegate:self];
[self.navigationController pushViewController:subviewController animated:YES];
[subviewController release];

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil andProperty1:(BOOL)p1 andProperty2:(NSArray *)p2 andProperty3:(enum SomeEnum)p3 andDelegate:(id<MyDelegateProtocol>)myDelegate {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
       self.property1 = p1;
       self.property2 = p2;
       self.property3 = p3;
       self.delegate = myDelegate;
    }
    return self;
}

そのため、事前定義されたinitメソッドを呼び出すのではなく、メインコントローラーで必要なことを何でも実行できます(そして、可能な初期化ごとに1つを作成する必要があります)。

何か悪いことですか?リテインサイクルはありますか?

4

5 に答える 5

3

ブロックを使用する利点は何ですか? 初期化子は、通常、インスタンスのプライベート状態を設定するために使用されます。ブロックが別の場所に実装されているため、このプライベート ステートにはブロックからアクセスできませんでした。

パブリック プロパティのみを使用する場合、初期化後に設定しないのはなぜですか?

SubViewController *vc = [[SubViewController alloc] initWithNibName:nil bundle:nil];
vc.property1 = NO;
vc.property2 = [NSArray array];
vc.property3 = SomeEnumValue;
vc.delegate = self;

それはまさにブロックバージョンが行うことです(面倒なことはありません)。

何か悪いことですか?リテインサイクルはありますか?

いいえ、しかし、アーキテクチャ上の理由からあなたの提案を却下します。クラスのカプセル化を破るか、初期化後にブロックが行うことを行うだけでは何の利点も得られません。

于 2012-10-09T10:19:43.937 に答える
2

質問は次のとおりです。

  1. この方法の利点は何ですか?
  2. このコードを効率的に管理できますか?

プログラムが成長すると、新しいレベルの呼び出しが追加され、コードの読み取り、保守、拡張、または開発が難しくなることに注意してください。将来のサブクラス化についても考えてください。将来、このコードをどのようにデバッグして、不一致の値を見つけますか。ブロックはコーディングを高速化できますが、デリゲート パターンを使用すると、コードがクリーンになり、1 つのスレッドで実行されるため、将来の保守が容易になります。これは、プロのプログラマーにとって真の価値です。

于 2012-10-09T10:06:15.650 に答える
1

あなたはあなたを定義することができます

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil completionHandler:(void (^)(id newObj))block;

のカテゴリのメソッドUIViewController。そこから呼び出しinitWithNibて、割り当てたばかりの完了ブロックを実行しますself

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil completionHandler:(void (^)(id newObj))block
{
    if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
        block(self);
    }
    return self;
}

これはうまくいくはずだと思います。

于 2012-10-09T10:03:37.700 に答える
1

これは可能です、retain問題ありません。すべてが同じスレッドで同期的に呼び出されます。

しかし 、これを単純な方法で行わないことの利点は何ですか - 後initに別のメソッドを呼び出すなど

MyController* controller = [[[MyController alloc] init] autorelease];
[self updateController:controller];
コードはinitメソッドから呼び出されていますか?

init...一般に、オブジェクトをさまざまな方法で初期化する場合は、個別のメソッドを作成することをお勧めします。

于 2012-10-09T10:21:01.967 に答える
1

なぜあなたがこのアプローチを取るのか、私にはよくわかりません (OOD 警察の注意を引きたい場合を除きます)。それは良い考えではありません

コントローラーは、代わりに必要な方法で初期化されたインスタンスを返す関数またはメソッドを定義できます。

于 2012-10-09T10:24:04.557 に答える