0

ブロック関数とコンテキストの値をテストしたい。テストコードは次のとおりです。

//xxx.h

@interface textObj :  NSObject 
@property (nonatomic, retain) NSNumber * num;
@end

typedef void (^ returnHandle)(NSNumber * res);

@interface BlockTest : NSObject

- (void) textBlock:(textObj *)num completionHandler:(void (^)(NSNumber * res))handler;

@end

//xxx.m

@implementation textObj
@synthesize num;

@end

@interface BlockTest (){
    returnHandle rt;
}

- (void)toggleChromeDisplay;

@end

@implementation BlockTest

- (void) dealloc{
    Block_release(rt);
    [super dealloc];
}

- (void)toggleChromeDisplay
{
    NSNumber *ret = [NSNumber numberWithInt:111];
    rt(ret);
}

void (^handle)(NSNumber * res, NSError *error);


- (void) textBlock:(textObj *)g1 completionHandler:(void (^)(NSNumber * res))handler
{
    rt = Block_copy(handler);
    [self performSelector:@selector(toggleChromeDisplay) withObject:nil afterDelay:0.5];
    return;
}

@end

テスト サンプルの呼び出しコードは次のとおりです。

//first sample code...
- (void)viewDidLoad
{
    [super viewDidLoad];

    test = [[BlockTest alloc]init];
    textObj * g1;
    g1 = [[textObj alloc] init];
    [g1 setNum:[NSNumber numberWithInt:10]];
    NSLog(@"main 0 g1 num=%@ count=%d", [g1 num], [g1 retainCount]);
    [test textBlock:g1 completionHandler:^(NSNumber *res) {
        NSLog(@"value=%@", [g1 num]);
        [g1 setNum:[NSNumber numberWithInt:20]];
        NSLog(@"main 1 g1 num=%@ count=%d", [g1 num], [g1 retainCount]);
    } ];
    NSLog(@"main 2 g1 num=%@ count=%d", [g1 num], [g1 retainCount]);
    [g1 release];
    NSLog(@"main 3 g1 num=%@ count=%d", [g1 num], [g1 retainCount]);  
}

ブロック関数では、g1 の値を変更できます。大丈夫です。しかし、g1 をテストの public 値として宣言すると、ブロック関数でエラーが発生します。g1にはアクセスできません。EXC_BAD_ACCESS(code=2, address=0x26) エラーを出力しました

//second sample code...
@interface UIMainViewController (){
@public
    textObj * g1;
}
@end

- (void)viewDidLoad
{
    [super viewDidLoad];

    test = [[BlockTest alloc]init];
    //textObj * g1;
    g1 = [[textObj alloc] init];
    [g1 setNum:[NSNumber numberWithInt:10]];
    NSLog(@"main 0 g1 num=%@ count=%d", [g1 num], [g1 retainCount]);
    [test textBlock:g1 completionHandler:^(NSNumber *res) {
        NSLog(@"value=%@", [g1 num]);
        [g1 setNum:[NSNumber numberWithInt:20]];
        NSLog(@"main 1 g1 num=%@ count=%d", [g1 num], [g1 retainCount]);
    } ];
    NSLog(@"main 2 g1 num=%@ count=%d", [g1 num], [g1 retainCount]);
    [g1 release];
    NSLog(@"main 3 g1 num=%@ count=%d", [g1 num], [g1 retainCount]);  
}

2 つの異なるサンプル コードを混同しています。2 番目のテスト コードがクラッシュするのはなぜですか?

4

2 に答える 2

3

保持カウントは役に立ちません。呼ばないで。決して。

定義により、retainCount はゼロを返すことはできません。未定義の、しばしばクラッシュする動作である割り当て解除されたオブジェクトをメッセージしています。

于 2012-06-20T14:41:18.187 に答える
1

主な問題は、@ H2CO3 が指摘しているようg1に、ブロックが実行される前に解放していることです。あるケースでは機能し、他のケースでは機能しない理由は、ブロックがコピー時に参照するローカル オブジェクト変数を保持するためです。

最初の例でg1は、メソッドスコープに対してローカルな変数であるため、ブロックはそれを保持します。

2番目の例でg1は、ivar(事実上self->g1)であるため、ブロックは保持されますself。ただしg1、ブロックを宣言した直後に解放するため、ブロックが を呼び出すとself->g1、割り当てが解除されているため、無効なポインターが取得g1されます。

于 2012-06-20T18:27:19.210 に答える