0

我有一個類似的方法:我是否需要複製一個塊,如果我使用它傳遞給它的方法?

- (void)loadStoreWithCompletion:(CompletionBlock)loadCompletion 
{ 
    dispatch_queue_t loadQueue = dispatch_queue_create("loadQueue", DISPATCH_QUEUE_SERIAL); 

    dispatch_async(loadQueue, ^{ 

     // ... Do background stuff ... 
    }); 

    dispatch_async(loadQueue, ^{ 

     dispatch_async(dispatch_get_main_queue(), ^{ 

      loadCompletion(); 
     }); 
    }); 

    dispatch_release(loadQueue); 
} 

我需要複製的loadCompletion塊,因爲它只可能會被調用時,這個方法的調用者不再存在,或者是罰款這樣的嗎?

回答

3

你可以依靠dispatch_async()做正確的事情與直接傳遞給它的塊。當一個塊被複制時,它也會複製任何被它捕獲的塊。由於內部塊引用了loadCompletion,因此它沒有用__block進行聲明,因此它被捕獲。換句話說,你很好。

0

這樣很好。但你應該在你的代碼中進行1次更改:

dispatch_async(loadQueue, ^{ 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     if (loadCompletion) { 
      loadCompletion();  
     } 
    }); 
}); 

你可以自己測試一下。如果您調用沒有任何參數的方法([instance loadStoreWithCompletion:nil];),則在您的代碼版本中,應用程序在調用完成處理程序時會崩潰。如果塊不存在(塊了),塊檢查將防止任何崩潰。

0

塊由調用者在堆棧上分配,這意味着一旦超出範圍,調用將導致錯誤。

你應該總是將它們複製到堆,當你打算以後使用它們(如在異步發生回調),您可以通過存儲它們直接調用[block copy]

  • 做到這一點無論是

    • 在財產被聲明爲copy

    記住,留住他們或者釋放他們並不總是工作,因爲他們可能會在堆棧中。

  • +0

    「你應該總是將它們複製到堆中」否,只有當你的函數將它存儲在某個將超過該調用的地方。 – newacct

    +0

    @newacct:我已經更具體了,通常塊是異步使用的,這就是爲什麼大多數情況下你需要複製它們。我想,如果他們不打電話,那麼你根本就不需要一個街區。 – Jack

    +0

    但是,如果您將它傳遞給一個函數,並且該函數將該塊存儲以供以後使用並與其執行異步處理,則該函數有責任在必要時複製它。你不需要知道(也不應該關心)被調用的函數做什麼來做正確的事情。 OP的函數不會將該塊存儲在實例變量或函數體內的任何位置。因此,他不需要複製它。在他的職能中發生的事情是重要的。 – newacct

    3

    在另一個塊內引用塊參數的行爲會導致它被隱式複製到堆中,因此您不需要明確地這樣做。

    +0

    僅當該塊被複制時 – newacct

    +0

    當然。這裏的要點是,如果需要處理它,它將自動處理。 – ipmcc

    相關問題