Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 给dispatch\u async时,块中的消息参数是否保留?_Ios_Objective C_Multithreading_Macos - Fatal编程技术网

Ios 给dispatch\u async时,块中的消息参数是否保留?

Ios 给dispatch\u async时,块中的消息参数是否保留?,ios,objective-c,multithreading,macos,Ios,Objective C,Multithreading,Macos,考虑以下方法片段 - (void) closeSocket { ... dispatch_async(dispatch_get_main_queue(), ^{ // last message before actual disconnection: [self.connectionListenerDelegate connectionDisconnected:self]; } self.connectionListenerDelegate = ni

考虑以下方法片段

- (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];
它保留了receiver和parameter对象(self),但我更喜欢GCD dispatch_async,我想更好地理解块

如果在某个后台线程上调用closeSocket,并在主线程上异步调度connectionDisconnected:并且我立即将对委托的弱引用置为空,那么该块可能会有一个nil对象,并且不会发送其消息

我认为在
self.connectionListenerDelegate=nil运行时,
dispatch
方法中的所有方法在访问
connectionListenerDelegate
时将获得
nil
引用

因此,最好的方法是将代理引用传输到临时对象,以便在块内使用:

id<ConnectionListenerDelegate> *tempDelegateRef = self.connectionListenerDelegate;

dispatch_async(dispatch_get_main_queue(), ^{
       // last message before actual disconnection:
       [tempDelegateRef connectionDisconnected:self];
   }

self.connectionListenerDelegate = nil;
id*tempDelegateRef=self.connectionListenerDelegate;
dispatch\u async(dispatch\u get\u main\u queue()^{
//实际断开前的最后一条消息:
[tempDelegateRef connectionDisconnected:self];
}
self.connectionListenerDelegate=nil;

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

为了澄清:您需要
dispatch\u async
块中的引用在块执行之前保持有效,但您担心其他东西可能会释放委托,导致
self.connectionListenerDelegate
设置为零?显示declar
connectionListenerDelegate
的初始化。通常,由于某种原因,委派很弱或未被保存。如果将self.connectionListenerDelegate=nil;放在块中,则即使异步调用closeConnection:,执行顺序仍将保持,并且connectionListenerDelegate只有在connectionDisconnecte之后才会变为nild已被调用。@Mottishner答案对您有用吗?我还没有时间彻底更改我的实现和测试-但我以前的代码中已经有过这种“技巧”(将委托放入堆栈变量,使其无效,然后使用(捕获的)异步调度)堆栈变量。首先,我不确定这确保了一次调用,并且这是线程安全的,接下来-我仍然没有关于dispatch_async捕获/不捕获我的self.delegate对象的明确答案。B.t.W-我的委托被弱引用。tempDelegateRef只是对self.connectionListenerDelegate.When connectionListe的引用nerDelegate变为零,tempDelegateRef也将指向同一个零。问题是如何解决的?是否
tempDelegateRef
保留旧对象?tempDelegateRef
是一个强引用,在最后一个所有者离开之前不会变为零。在这种情况下,这就是块。@KunalShrivastava.检查。即使
也一样>self.connectionListenerDelegate
设置为nil,
tempDelegateRef
仍将指向旧对象。@Avi:是的,它是一个强“引用”。但它所引用的对象是connectionListenerDelegate,该对象正在手动设置为nil。执行顺序可能并不总是与异步块中使用的tempDelegateRef相同。可能存在这样的情况:首先将connectionListenerDelegate设置为nil,然后执行异步块。