//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
精彩评论