4

ブロックは目的の c オブジェクトであり、ARC を使用する場合は Block_copy なしで NSDictionary に直接配置できることを理解しています。 しかし、次のコードで EXC_BAD_ACCESS エラーが発生しました。

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self method1:^(BOOL result){
        NSLog(@"method1WithBlock finished %d", result);
    }];
}

- (void) method1:(void (^)(BOOL))finish{

    NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:^(NSData *rcb){
        finish(YES);
    }, @"success",
                          ^(NSError *error){
                              finish(NO);
                         }, @"failure",  nil];

    [self method2:dict];
}


- (void) method2:(NSDictionary *)dict{
    void (^success)(NSData *rcb) = [dict objectForKey:@"success"];
    success(nil);
}

method1: をこれに変更すると、エラーは発生しません。

- (void) method1:(void (^)(BOOL))finish{
    void (^success)(NSData *)  = ^(NSData *rcb){
        finish(YES);
    };

    void (^failure)(NSError *error) = ^(NSError *error){
        finish(NO);
    };
    NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:success, @"success",
                          failure, @"failure",  nil];
    [self method2:dict];
}

ブロックを辞書に入れる前に、自動変数を使用してブロックを格納する必要がある理由を誰か説明できますか?

iOS SDK 6.1 を使用しています。

4

3 に答える 3

5

「ARCリリースノートへの移行」によると、辞書に保存されているブロックをコピーする必要があります(強調鉱山):

リターンなど、ARCモードでブロックをスタックに渡すと、ブロックは「機能します」。もう Block Copy を呼び出す必要はありません。 スタックを「下に」渡すときに 、および保持を行う他のメソッドを使用する必要があります[^{} copy]arrayWithObjects:

と はヒープにコピーする必要がある「スタックベースのブロック」ではないため success、2番目の方法は「偶然」機能します。failure__NSGlobalBlock__

于 2013-07-20T13:59:24.673 に答える
0

ブロックは目的の c オブジェクトであり、ARC を使用する場合は Block_copy なしで NSDictionary に直接配置できることを理解しています。

いいえ、それらは一般的なオブジェクトではありません。ブロックを作成すると、それはスタック上にあり、保持カウントが何であるかは関係ありません。関数を終了すると、スタックからポップされます。それをコピーして、存続させます。

于 2013-07-20T14:01:27.823 に答える