目标C阻止为异步回调&不良访问 [英] Objective C Blocks as Async-callbacks & BAD ACCESS
问题描述
我有一个严重的疑问.假设以下情况:
I've got a serious doubt. Suppose the following scenario:
- 您的屏幕上显示
UIViewController
. - 例如,该应用使用块作为回调来发起后端调用
- 您使用自我"替代品来防止保留周期.
- 用户单击返回",并且
UIViewController
被取消分配. - 迟早会执行回调块>>
BAD ACCESS
- You have a
UIViewController
onscreen. - The app initiates, say, a backend call using a block as a callback
- You use a 'self' surrogate, to prevent retain cycles.
- The user hits 'Back', and the
UIViewController
gets dealloc'ed. - Sooner or later, the callback block gets executed >>
BAD ACCESS
在iOS 4之前,我们通过将nil
的delegate
属性设置为...我不知道,不管您使用的是哪种类,来处理这种情况.
Before iOS 4, we dealt with this kind of situation by setting to nil
the delegate
property of... i don't know, whatever class you were using.
但是现在...如何取消封锁?如果将块发送到静态方法又没有办法清除该回调引用,该怎么办??
But nowadays... how do you cancel a block??. What if the block was sent to a static method, and you have no way of wiping out that callback reference??.
在那种情况下,我们应该避免使用自我"替代吗?
In that case, should we avoid using the 'self' surrogate?
顺便说一句,用自我"替代,我的意思是说:
BTW, by 'self' surrogate, i mean to say:
__block typeof(self) bself = self;
谢谢!
推荐答案
首先,首先:
如果(并且仅当)您避免使用self
或直接访问块内部的ivars的原因确实是保留周期,那么您应该处于类似
Well, first off:
If (and only if) your reason for avoiding the use of self
or direct access of ivars inside of a block really are retain-cycles, then you should be in a situation like
client => objectA => blockWithWeakBackReference
(其中=>
表示有很强的参照力").
(where =>
means 'has a strong reference to').
在这种情况下,blockWithWeakBackReference
仅应由objectA
调用,因此不存在访问错误的危险.
In this case, blockWithWeakBackReference
should only ever be invoked by objectA
, so there is no danger of a BAD ACCESS.
如果我正确理解了您的问题,那么您真正的意思是另一种情况:
If I understand your question correctly, what you really mean is a different scenario:
-
如果满足一些先决条件,
-
objectA
希望某些应用程序范围内的服务代表其执行块 . - 您避免在块内使用
self
,因为您希望能够在执行块之前处置objectA
.
objectA
wants some application-wide service to execute a block on its behalf, if some precondition is met.- You avoid using
self
inside of the block because you want to be able to dispose ofobjectA
before the block is executed.
一个示例可能是共享网络队列,当请求由于某种原因而完成加载时,该网络将执行一个块.
One example for this might be a shared network-queue that executes a block when the request finished loading for one reason or another.
在这种情况下,我建议您简单地复制NSNotificationCenter
的addObserverForName:object:queue:usingBlock:
的设计,并让您的服务实现一对-(SomeTokenObjectType)addWorkerBlock:(void(^)(whatever-signature-makes-sense-for-you))
和-(void)cancelWorkerBlockWithToken:(SomeTokenObjectType)
之类的方法,以排队并取消您的回调-块.
In that case, I would suggest to simply copy the design of NSNotificationCenter
's addObserverForName:object:queue:usingBlock:
and make your service implement a pair of methods like -(SomeTokenObjectType)addWorkerBlock:(void(^)(whatever-signature-makes-sense-for-you))
and -(void)cancelWorkerBlockWithToken:(SomeTokenObjectType)
in order to enqueue and cancel your callback-blocks.
然后,所有使用此服务的对象都可以简单地具有一个NSMutableSet
类型的ivar,以为每个排队的块存储令牌,并且-在其dealloc
中-枚举其余令牌,并通过服务将其取消.
Then, all objects that use this service can simply have an ivar of type NSMutableSet
to store the token for every enqueued block and — in their dealloc
— enumerate the remaining tokens, canceling them with the service.
这篇关于目标C阻止为异步回调&不良访问的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!