Blocks memory management
There is a conceptual overview of Blocks objects in objective-c within this Apple reference:
http://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Blocks/Blocks.pdf
However, it does not really explain two topics that concern me and may concern other people. The first question is like that: can I assign a nil to a Block reference? Or should I use NULL? Or can I use neither of them?
The second problem lies in the sphere of memory management. Say, I have declared such a method creating a block object on the stack.
-(void)makeTheClass
{
TheClass *object = [[TheClass alloc] init];
object.blockReference = ^(void) { return nil; }
}
This object, being created within some scope, is going to be destroyed after it goes out of it. But TheClass object is actually g开发者_StackOverflow社区oing to store a reference to this (nearly destroyed) Block:
typedef id (^WeirdBlockType)(void);
@interface TheClass {
WeirdBlockType blockReference;
}
How do I declare a class property for such a block? What's the difference between these two:
@property (nonatomic, retain) WeirdBlockType blockReference;
@property (nonatomic, copy) WeirdBlockType blockReference;
?
It is clearly said in the Apple documentation that block copying moves the block to the heap. But what if I just retain it? Is it going to be destroyed after it goes out of makeTheClass
method scope?
Well I've found the solution. Thanks to Gojan for his answer, but he was actually wrong in one place:
Wevah was right. Retain on a block has no effect until it is completely moved to the heap, and only Block_copy
accomplishes such a task.
Perhaps blocks are not the only objects that cannot be retained while they are on the stack; but whilst you create (alloc
and init
) any NSObject
subclass instances on the heap by default, you don't care about it - retain
works as usual. Block objects are created on the stack by default, that's why the work a little unexpectedly.
Thanks everybody!
can I assign a nil to a Block reference? Or should I use NULL?
nil can be read as "an empty id
type" and NULL is defined like ((void *)0)
. The difference here is the context. If you are working with NSObject's based objects you should use nil.
In the case of blocks you should use nil because you can interact with the block like if it was an NSObject (you can retain it, release it, etc). But if you use NULL it should work.
How do I declare a class property for such a block? What's the difference between these two:
@property (nonatomic, retain) WeirdBlockType blockReference; @property (nonatomic, copy) WeirdBlockType blockReference;
?
In the documentation says:
If you are using Objective-C, you can send a block copy, retain, and release (and autorelease) messages.
So both declarations are valid, but if you ask my I prefer retain
than copy
.
In conclusion:
Blocks are treated like objects defined and instantiated at the same time (runtime) so after you get a perdurable reference to it you can think that reference like any other object.
精彩评论