请考虑以下方法摘要。
- (void) closeSocket {
...
dispatch_async(dispatch_get_main_queue(), ^{
// last message before actual disconnection:
[self.connectionListenerDelegate connectionDisconnected:self];
}
self.connectionListenerDelegate = nil;
...
}
我的“socket”实现类的这个方法可以由外部对象调用,在某个任意线程(main或其他)中。我希望只在主线程上通知我的代理一次,并删除代理,以便其他后台事件和可能的传入数据无法到达。
换句话说,我想确保connectionDisconnected:
是从套接字到委托的最后一次调用。
我知道代码块会捕获它们的环境变量等。但是块会在创建时捕获并保留self.connectionListenerDelegate
吗?
如果在某个后台线程上调用closeSocket
,并在主线程上异步调度connectionDisconnected:
,并且我立即取消对我的委托的弱引用 - 可能该块将为nil对象并不会发送消息?
正确的方法是什么?
我想我可以使用旧的
[self.connectionListenerDelegate performSelectorOnMainThread:@selector(connectionDisconnected:) withObject:self waitUntilDone:NO];
保留了接收器和参数对象(self),但我更喜欢GCD dispatch_async,我想更好地理解块。
答案 0 :(得分:2)
如果在某个后台线程上调用了closeSocket,并在主线程上异步调度connectionDisconnected,并且我立即取消对我的委托的弱引用 - 也许该块将有一个nil对象并且不会发送它消息?
我认为在self.connectionListenerDelegate = nil;
运行后,dispatch
方法中的所有方法在访问nil
时都会获得connectionListenerDelegate
引用。
因此,最好的方法是将委托引用转移到临时对象以便在块内使用:
id<ConnectionListenerDelegate> *tempDelegateRef = self.connectionListenerDelegate;
dispatch_async(dispatch_get_main_queue(), ^{
// last message before actual disconnection:
[tempDelegateRef connectionDisconnected:self];
}
self.connectionListenerDelegate = nil;
我不确定你是否需要强弱/弱引用或类似的东西。