Objective c i';我试图从一个obj-c块访问一个类ivars,该块';它被定义为类的一部分。什么不';我不明白吗?

Objective c i';我试图从一个obj-c块访问一个类ivars,该块';它被定义为类的一部分。什么不';我不明白吗?,objective-c,objective-c-blocks,Objective C,Objective C Blocks,只要函数“c.test()”访问简单的IVAR,即char、int等,c.test()就会执行并干净地返回。如果我试图访问obj-c对象,就会出现异常。 我遗漏了什么?您没有在init方法中保留数组,也没有调用setter方法。街区也是如此;如果您希望对象在当前方法的持续时间之后仍然保留,则需要通过调用setter方法或调用retain(或在块的情况下调用copy)来获得它们的所有权 您的错误与块无关,而与内存管理有关。请注意,如果使用垃圾收集,仍然需要调用copy以使块移动到堆中您没有在ini

只要函数“c.test()”访问简单的IVAR,即char、int等,c.test()就会执行并干净地返回。如果我试图访问obj-c对象,就会出现异常。
我遗漏了什么?

您没有在init方法中保留数组,也没有调用setter方法。街区也是如此;如果您希望对象在当前方法的持续时间之后仍然保留,则需要通过调用setter方法或调用
retain
(或在块的情况下调用
copy
)来获得它们的所有权


您的错误与块无关,而与内存管理有关。请注意,如果使用垃圾收集,仍然需要调用copy以使块移动到堆中

您没有在init方法中保留数组,也没有调用setter方法。街区也是如此;如果您希望对象在当前方法的持续时间之后仍然保留,则需要通过调用setter方法或调用
retain
(或在块的情况下调用
copy
)来获得它们的所有权


您的错误与块无关,而与内存管理有关。请注意,如果使用垃圾收集,仍然需要调用copy以使块移动到堆中

BJ正确的是,您需要遵循内存管理规则,但在这种情况下,答案与块有关

由于您的代码当前处于状态,
array
的普通属性将一直工作,直到当前自动释放池耗尽。如果您alloc/init这些“class1”对象中的一个,并立即尝试使用
array
属性,则该属性将起作用(因为在初始化对象和尝试访问数组之间不会耗尽自动释放池)

然而,一旦你把积木放进去,情况就不再是这样了。当您使用
^{…}
语法声明块时,该块将在调用堆栈的当前帧中分配。从init方法返回
时,会弹出当前帧。块ivar仍保留内存地址,但该地址不再存在块。它在移除堆栈框架时被销毁

避免这种情况的方法是将块从堆栈复制到堆上,然后改用该块:

//class definition
@interface class1 : NSObject {
    NSMutableArray *array ;
    void (^test)() ;
}
@property( nonatomic,assign ) NSMutableArray *array  ;
@property( nonatomic,readonly ) void (^test)()  ;
@end

// implementation

@implementation class1

@synthesize array ;
@synthesize test ;

- (id)init
{
    self = [super init];
    a = [NSMutableArray arrayWithObjects:@"1",@"2", nil] ;
    test = ^ () {
        NSLog(@"length of array = %d",(int)[array count]);
    } ;
    return self;
}

// from main

    class1 *c = [[class1 alloc] init] ;

    c.test();

BJ是正确的,您需要遵循内存管理的规则,但在本例中,答案确实与块有关

由于您的代码当前处于状态,
array
的普通属性将一直工作,直到当前自动释放池耗尽。如果您alloc/init这些“class1”对象中的一个,并立即尝试使用
array
属性,则该属性将起作用(因为在初始化对象和尝试访问数组之间不会耗尽自动释放池)

然而,一旦你把积木放进去,情况就不再是这样了。当您使用
^{…}
语法声明块时,该块将在调用堆栈的当前帧中分配。从init方法返回
时,会弹出当前帧。块ivar仍保留内存地址,但该地址不再存在块。它在移除堆栈框架时被销毁

避免这种情况的方法是将块从堆栈复制到堆上,然后改用该块:

//class definition
@interface class1 : NSObject {
    NSMutableArray *array ;
    void (^test)() ;
}
@property( nonatomic,assign ) NSMutableArray *array  ;
@property( nonatomic,readonly ) void (^test)()  ;
@end

// implementation

@implementation class1

@synthesize array ;
@synthesize test ;

- (id)init
{
    self = [super init];
    a = [NSMutableArray arrayWithObjects:@"1",@"2", nil] ;
    test = ^ () {
        NSLog(@"length of array = %d",(int)[array count]);
    } ;
    return self;
}

// from main

    class1 *c = [[class1 alloc] init] ;

    c.test();

+1原则上是正确的,但在这种情况下,正确的答案与积木有关。嗯,我想这是真的。但我的观点是,只有当内存管理错误时,才会出现这个问题。(虽然我猜这在GC下是不正确的,所以你的观点是正确的。)+1原则上是正确的,但在这种情况下,正确的答案确实与块有关。嗯,我猜这是正确的。但我的观点是,只有当内存管理错误时,才会出现这个问题。(虽然我猜在GC下不是这样,所以你的观点是正确的。)如果构建和分析没有抓住这一点,我会感到惊讶(和沮丧)。如果没有,请提交一个bug(OP)。我想我明白了。分配块时,我在堆栈上创建了一个对象,因此我需要将其从堆栈中复制出来,以便正确地将其分配给“测试”ivar。复制将自动增加保留计数,所以在我完成复制后需要释放它。@bbum刚刚签入4.0,但它没有捕获它。我正在下载4.0.1,看看它是否在里面。@ron完全正确!您需要在
-dealoc
方法中执行
[testrelease]
。@bbum作为rdar://9230700I 如果构建和分析没有发现这一点,我们会感到惊讶(和沮丧)。如果没有,请提交一个bug(OP)。我想我明白了。分配块时,我在堆栈上创建了一个对象,因此我需要将其从堆栈中复制出来,以便正确地将其分配给“测试”ivar。复制将自动增加保留计数,所以在我完成复制后需要释放它。@bbum刚刚签入4.0,但它没有捕获它。我正在下载4.0.1,看看它是否在里面。@ron完全正确!您需要在
-dealoc
方法中执行
[testrelease]
。@bbum作为rdar://9230700