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 声明为测试的公共值时,它会在块函数中出错。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]);  
}

我混淆了两个不同的示例代码,为什么第二个测试代码会遇到崩溃?

4

2 回答 2

3

保留计数是无用的。不要叫它。永远不会。

根据定义,retainCount 不能返回零。您正在向一个已释放对象发送消息,该对象是未定义的,通常是崩溃的行为。

于 2012-06-20T14:41:18.187 回答
1

主要问题是,正如@H2CO3 指出的那样,您在g1执行块之前释放。它在一种情况下起作用而不在另一种情况下起作用的原因是块保留了它们在复制时引用的任何局部对象变量

在您的第一个示例中,g1是方法范围的本地变量,因此块保留它。

在您的第二个示例中,g1是一个 ivar(有效self->g1),因此该块保留self. 但是您g1在声明块后立即释放,因此当块调用时self->g1,它会获得一个无效指针,因为g1已被释放。

于 2012-06-20T18:27:19.210 回答