2012-03-14 28 views
4

出於某種原因,我希望有一個塊運行循環的下一次迭代過程中執行的,所以我想出了:ARC __bridge投Block_copy&Block_release

typedef void (^resizer_t)() ; 

- (void) applyResizer: (resizer_t) resizer { 
    resizer() ; 
    Block_release(resizer) ; 
} 

- (void) usage { 
    ... 
    resizer_t resizer = ^() { 
     // stuff 
    } ; 

    [self performSelectorOnMainThread:@selector(applyResizer:) 
          withObject:(__bridge id) Block_copy((__bridge void *) resizer) 
         waitUntilDone:NO] ; 
} 
  1. 是不是很諷刺的是,我有投給無效*參數爲 Block _copy?
  2. 爲什麼編譯器在Block_copy上阻塞 而我的Block_release沒有橋接void * cast?

的代碼似乎工作,我沒有發現泄漏,也沒有過早釋放,但我是一個有點語法困惑......

回答

13

塊被視爲對象,因此ARC阻止你從鑄造到void *沒有明確的橋接演員。奇怪的是你的編譯器不會在Block_release上抱怨:它應該(在我的機器上)。

由於ARC將塊視爲對象,因此您不需要再使用Block_copyBlock_release。如果要將其移動到堆並讓編譯器管理其餘部分,請複製該塊(使用-[NSObject copy])。

-[NSObject performSelectorOnMainThread:withObject:waitUntilDone:]保留接收器和參數對象,直到調用該方法。因此,您的區塊將在需要時保留併發布。您只需確保在將塊傳遞給該方法之前,通過發送copy消息來確保塊未存儲在堆棧中。此外,還有一種更簡單的方式來分派塊的執行:它是libdispatch(又名GCD)。

dispatch_async(dispatch_get_main_queue(), resizer); 
+0

這是明確的答案。我也推薦@verec和主隊列一起使用dispatch_async。 – 2013-09-17 02:41:48

4

我想塊運行循環

井的下一次迭代中執行,這就是爲什麼你有dispatch_after。如果你提供一個微小的時間值,它將會產生你所追求的效果:你給出一個塊,並且當前的runloop完成並且重繪時刻發生後,塊將立即執行。

或者,如果您可以在沒有堅持阻止的情況下生活,請使用具有微小延遲值(甚至爲零)的performSelector:withObject:afterDelay:。這也有同樣的效果。

你要求的是被稱爲「延遲表現」,並且很常見。因此,以通用的方式,框架給你的方式去做;不要試圖像你的代碼所做的那樣讓所有的奇怪和幻想變成現實。