2

私がやろうとしていることが可能かどうかはわかりません。私はブロックの経験がなく、いくつかのチュートリアルを読んだだけで、そのアイデアが本当に気に入っています。私のクラスAppointmentView.h(およびm)はViewControllerを拡張しています。これには、別のClass Appointmentのメンバーであるいくつかのプロパティが含まれており、そのクラスにはいくつかのNSArrayがあります。グループ化されたテーブルビューを作成するために、配列の値を確認してから、表示される値を適切にコピーします(あまり凝ったものや複雑なものはありません)。通常、私はif-elseステートメントを使用し、適切に制御しますが、ブロックを確認した後、次のことが実行可能かどうかを考えさせられました。

[self setOutcomes: [[NSArray alloc] initWithObjects:
                        ^{ return [myAppointment.CANCELED isEqualToString:@"NO"] == YES ? 
                                                            [[NSString alloc] initWithString:@"Not Cancelled"] :
                                                            [[NSString alloc] initWithString:@"Cancelled"]; },
                        ^{ return [myAppointment.CANCELED isEqualToString:@"NO"] == YES ?
                                                            [[NSString alloc] initWithString:@"No Cancellation reason"] :
                                                            [[NSString alloc] initWithString:myAppointment.CANCREASON]; },
                        ^{ return [myAppointment EVENTS].length > 0 ?
                                                            [[NSString alloc] initWithString:myAppointment.EVENTS] :
                                                            [[NSString alloc] initWithString:@"No Events"]; },
                        ^{ return [myAppointment SUMMARY].length > 0 ?
                            [[NSString alloc] initWithString:myAppointment.SUMMARY] :
                            [[NSString alloc] initWithString:@"No Summary"]; },
                        nil]];

このコードは正常にコンパイルされますが、実行するとクラッシュします。私の理解では、これは間違っています。なぜなら、列挙に毎回コードを実行するように指示しているからです。だから、これは私が望むものではありません。それから私は次のことを試みました:

   [self setOutcomes: [[NSArray alloc] initWithObjects:
                        [[NSString alloc] initWithString: (NSString *) ^(void){ 
                                                                        return [myAppointment.CANCELED isEqualToString:@"NO"] == YES ?
                                                                                                        @"Not Cancelled" : @"Cancelled"; }],
                        [[NSString alloc] initWithString: (NSString *) ^(void){ 
                                                                        return [myAppointment.CANCELED isEqualToString:@"NO"] == YES ? 
                                                                                                        @"No Cancellation reason" : myAppointment.CANCREASON; }],
                        [[NSString alloc] initWithString: (NSString *) ^(void){ 
                                                                        return [myAppointment.EVENTS isEqualToString:@""] == YES ? 
                                                                                                        myAppointment.EVENTS : @"No Events"; }],
                        [[NSString alloc] initWithString: (NSString *) ^(void){ 
                                                                        return [myAppointment.SUMMARY isEqualToString:@""] == YES ?
                                                                                                        myAppointment.SUMMARY : @"No Summary"; }],
                        nil]];

これは正常にコンパイルされますが、次のエラーでクラッシュします。

-[ NSMallocBlockの長さ]:認識されないセレクターがインスタンス0x6bd68f0に送信されました

また、使用できるジェネリックメソッドを型定義しようとしましたが、どちらも役に立ちませんでした。それで、私は疑問に思いました、これは可能ですか?このコードでは、if-else(通常のように)を使用してそれを実行できることを知っていますが、他の状況では、このような動的コード生成オプションは非常に便利です。

どちらのNSStringもこれを処理する方法を知らないので、オプションを使用して拡張する必要があると感じました。

initWithBlock:

または、ここで何か他のものが欠けています。またはそれは不可能かもしれません....(?)

PS:NSArrayのenumerateUsingBlock:メソッドを見たばかりですが、配列内の各エントリが他のエントリとは完全に異なり、特定のブロックが基準に適合しないため、これがこの場合の目的に役立つかどうかはわかりません。

4

2 に答える 2

3

イニシャライザで単純な選択を行う必要がある場合は、ブロックは必要ありません。

[NSArray initWithObjects:
         ([myAppointment.CANCELED isEqualToString:@"NO"] ? @"Not Cancelled" : @"Cancelled"),
         ([myAppointment.CANCELED isEqualToString:@"NO"] ? @"No Cancellation reason" : myAppointment.CANCREASON),
         nil];

括弧を使用して ?: 演算子を囲みます。


同じ場所でブロックを定義して呼び出す方法の質問に答えるために更新されました

この単体テストは私のために働いた:

- (void)testBlockNow
{
    BOOL X = ^{ return YES; }();
    STAssertTrue(X, nil);
}

それは簡単です:^{ … }ブロックを定義してから、ブロック()を呼び出します。

于 2012-05-23T12:32:47.943 に答える
2

はい、ブロックを配列に格納できますが、それについては賢明である必要があります。

typedef (void)(^X)();

X block1 = ^{ … };
X block2 = ^{ … };
X block3 = ^{ … };

NSArray *array = [NSArray initWithObjects:
                  [[block1 copy] autorelease],
                  [[block2 copy] autorelease],
                  [[block3 copy] autorelease],
                  nil];
于 2012-05-23T12:07:27.160 に答える