作者Esvent (Esvent)
看板MacDev
标题[问题] Delegate Callback与Main Thread的问题
时间Wed Dec 3 23:42:08 2014
各位好,
最近在写一个架构上出了点问题,想要请教一下
问题:
如何在background thread触法一个应在main thread上执行的delegate callback,
且在delegate dealloc的时候,可清掉已注册在main runloop上却还没被执行的callback
问题完整版:
问题是这样的,我写了一个会自行跟伺服器抓图的Class A,
实体化後的Object A会运行在他自己开的Thread上,
并且会提供一个delegate callback,把抓到的图丢回给delegate
然後我又写了一个UIView B,并把他注册为Object A的delegate
但是这样一来,如果在B实作的callback里直接把图画到画面上,
就一定得自己在main thread上呼叫一次display画面才会更新(因为在A的thread)
所以我想说,若是Class A在触法delegate的callback的时候,
直接在main thread上触法就好,
於是我就在Class A用了performSelectorOnMainThread方法来触法callback,
但是这样却又会出现一个问题,就是如果某一天我把UIView B杀掉後,
main runloop上却还有来不及被执行的callback的话,就会造成EXC_BAD_ACCESS...
目前我想到的解决的办法
1. 设定performOnMainThread 的 waitUntilDone 为 YES
但是这会block住抓图的thread, 这样另外开thread的意义就不是很大
2. 在UIView B dealloc的时候清掉main runloop上以B为对象的callback
或是Object A dealloc的时候,清掉自己发出且还未执行的callback
google了一个早上,好像没有办法清掉..(要在同个thread才行)
3. 在B实作的callback里面自己呼叫更新UI的方法
其实就是想避免这个
想问一下这该如何达成? 感谢各位前辈的提点
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 220.135.62.74
※ 文章网址: http://webptt.com/cn.aspx?n=bbs/MacDev/M.1417621332.A.4A8.html
1F:→ darktt: 在B销毁的时候将Delegate设定成nil即可 12/04 00:09
感谢提醒,我有在B的dealloc设定A的delegate 为 nil
2F:推 kiii210: 咦,delegate的property设成weak不是可以避免这种问题吗? 12/04 00:22
3F:→ uranusjr: Yeah, weak property 应该会自动在目标消失时 nil-out 12/04 00:31
4F:→ uranusjr: 如果有问题请附上简单范例 12/04 00:33
刚刚试了一下weak property,还是有同样的问题QQ
下班之後我再附上完整范例
5F:→ darktt: 主要是A在另外一个thread,它的delegate没有与main thread 12/04 09:02
6F:→ darktt: 同步所造成的 12/04 09:02
A其实是隶属於B的一个子元件,并且A会在thread开始与结束时retain/release delegate
然後B会在viewDdidDisappear的时候把A停掉
所以应该是不会有B比A早死的状况,也不会有同步的问题吧..?我猜
7F:推 howdiun: respondsToSelector有加吗 12/04 09:10
是的,A的程式码大概长这样:
// A的Thread method
- (void)threadA {
[delegate_ retain];
while(![NSThread currentThread].isCancelled) {
if (delegate_ && [delegate_ respondsToSelector:@selector(callback)] {
NSMethodSignature *signature =
[(NSObject *)delegate_ methodSignatureForSelector:@selector(callback)];
NSInvocation *invoke =
[NSInvocation invocationWithMethodSignature:signature];
[invoke setTarget:delegate_];
[invoke setSelector:@selector(callback)];
[invoke setArgument:&self atIndext:2];
...
[invoke performSelectorOnMainThread:@selector(invoke)
withObject:nil
waitUintilDone:NO];
}
}
[delegate_ release];
}
// B的dealloc
- (void)dealloc {
[A setDelegate:nil];
[A release];
A = nil;
...
[super dealloc];
}
※ 编辑: Esvent (220.135.62.74), 12/04/2014 10:33:35
8F:→ uranusjr: Delegate 会 release owner 怎麽看都怪... 12/04 10:38
9F:→ uranusjr: 这应该只是名词的问题而已就是了, 其实它们两个不是真的 12/04 10:38
10F:→ uranusjr: delegate 关系, 比较像 target-action 12/04 10:39
11F:→ Esvent: 找到一个方法..在B的dealloc让mainRunLoop多跑个几秒就ok 12/10 19:00
12F:→ Esvent: 不过因为没有检查到底有没有跑完..所以还是有很低的机率会 12/10 19:01
13F:→ Esvent: 当掉 12/10 19:01