开发者

i'm trying to access a classes ivars from a obj-c block that's defined as part of the class. what don't i understand here?

//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 a开发者_高级运维rrayWithObjects:@"1",@"2", nil] ;
    test = ^ () {
        NSLog(@"length of array = %d",(int)[array count]);
    } ;
    return self;
}

// from main

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

    c.test();

as long as the function "c.test()" accesses simple ivars, i.e. char, int, etc. c.test() executes and returns cleanly. i try to access an obj-c object, i get exceptions. what am i missing?


BJ's correct that you need to follow the rules of memory management, but in this case, the answer does have to do with blocks.

As your code currently stands, the normal property of array will work until the current autorelease pool drains. If you alloc/init one of these "class1" objects and immediately attempt to use the array property, it will work (because no autorelease pool will have been drained between the initialization of the object and the time at which you attempt to access the array).

However, once you put the block in there, this is no longer the case. When you declare a block using the ^{ ... } syntax, this block is allocated in the current frame on the call stack. When you return from the init method, the current frame is popped. The block ivar still holds a memory address, but a block no longer exists at that address. It was destroyed when the stack frame was removed.

The way to avoid this is to copy the block off of the stack and onto the heap, and then use that block instead:

test = [^{  NSLog(@"block!"); } copy];


You're not retaining the array in your init method, and you're not calling the setter method either. Likewise for the block; if you want your objects to stick around past the duration of the current method, you need to take ownership of them, either by calling your setter methods or calling retain (or copy in the case of the block).

Your error has nothing to do with blocks, and everything to do with memory management. Note that if you're using garbage collection, you still need to call copy to cause the block to be moved to the heap

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜