Objective C Blocks: Is there a way to avoid 'self' being retained?
I discussed this topic with Apple support, and they told me what I had expected: currently, there is no way that would let me tell the block that it should not retain self. However, they offered two ways to work around the problem.
The first would be to pass self as an argument to the block rather than a block variable. The API would become:
[self addEventListenerForType:ADDED_TO_STAGE
block:^(id selfReference, SPEvent *event)
The API would thus be responsible for passing in the (non-retained) self. Developers would still have to be told that they have to use this reference instead of self, but at least it would be easy to use.
The other solution that Apple has used in this sort of situation is to provide a separate method from release/dealloc for shutting down the listener. A good example of this is the "invalidate" method of NSTimer. It was created because of a memory cycle between NSRunLoop and NSTimer (by design).
This is a nice way to do it. But, for the record, aliasingself
with a __block
variable will prevent retention as well.
http://stackoverflow.com/questions/3975675/objective-c-blocks-is-there-a-way-to-avoid-self-being-retained
从以上的讨论中,我没没有办法让block引用参数而不导致selfretain的方法,但是提到了三种方式来实现在block中引用参数而不导致self retain的解决方案:
1 将当前对象当做block的参数传进去,其形式:
[request getRaidersFrompageNum:pageNum finished:^(id target,id result, ServerResponseState state)
{
[(RaidersViewController *)target getRaidersInfoAndShow:state response:result pageNum:pageNum];
}];
- (void)blockTimer
{
__block TestViewController *blockSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
blockSelf->_timer=[NSTimer scheduledTimerWithTimeInterval:1.0
target:blockSelf
selector:@selector(caculateLeftTimeForTomorrow)
userInfo:nil
repeats:YES] ;
[[NSRunLoop currentRunLoop] addTimer:blockSelf->_timer forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] run];
});
}
将self手动转化为__block类型,这样即可使block不在retain self