在给予dispatch_async时,块中的消息参数是否保留?

时间:2015-11-26 12:59:24

标签: ios objective-c multithreading macos

请考虑以下方法摘要。

- (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,我想更好地理解块。

1 个答案:

答案 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;

我不确定你是否需要强弱/弱引用或类似的东西。