IOS Blocks 詳細介紹 – iPhone手機開發技術文章 iPhone軟體開發教學課程

  • block類似與函數指針,與函數指針的區別在於其可以捕獲(capture)其定義時作用域內的變量,當在其他位置調用時仍然可以使用。

  • block是一種Objective-C對象,其數據結構中存在isa指針,isa指針指向&_NSConcreteStackBlock或&_NSConcreteGlobalBlock。

  • block通常是在函數內定義的,此時block對象是在棧內分配的,若此block隻在定義它的函數內使用,則block就會一直存在在棧中,當函數返回時,棧幀回退,定義的block也隨之銷毀。

  • 當block需要在其定義時的函數外使用時,需要對其進行copy處理,copy的意義在於將block在堆中分配一份,這樣當定義函數的棧幀回滾時,block仍然存在。
    1. copy操作可以向block對象發送-copy消息,也可使用C函數Block_copy(),釋放操作則為-release或Block_release().

    2. 對block應該總是進行copy操作,因為對棧內分配的block拷貝會將其拷貝到堆中,對已經在堆中的block進行copy,則隻會增加retain count,與retain操作相同。而對棧內分配的block進行retain操作則不會有任何影響。

    3. block之所以強大在於其可以捕獲(capture)其引用的變量,包括局部變量,指針,Objective-C對象,全局變量,static變量等。
      1. 全局變量,static變量在block內是直接訪問的,因為其內存區域一直存在。

      2. 對於引用的局部變量,block使用的方法是將局部變量拷貝到block內部,並聲明為const,這樣在block中將隻能使用引用到局部變量的初始值,而不能進行修改。

      3. 局部指針變量被block const拷貝後仍然是指針,雖然指針本身是const的,但其指向的對象仍然是可以修改的。

      4. 如果想對引用的局部變量進行修改,可以在局部變量上使用__block標示符號,使用__block後的局部變量會以一種指針的方式被間接引用,引用其的block不會進行const copy,所有block、包含定義的函數內看到的__block局部變量都是同一份,任何block中對此變量進行修改都可以被其他block看到。在引用__block局部變量的block被從棧拷貝到堆時,__block變量也會被拷貝到堆中,所以__block變量在運行時是會變化的。

      5. 在block引用Objective-C對象時,會對Objecitive-C對象進行retain操作,當block銷毀時再進行release操作。如果不想對引用的Objecitive-C對象做retain處理,則可以使用__block 標示要引用的Objecitive-C對象,這隻適用於非ARC的代碼中。在ARC代碼中,即使用__block標示,在block引用時仍然會retain,這中情況下則需要使用__weak(iOS5)或__unsafe_unretained(iOS4,不支持weak的環境)。

      6. 如果在類方法中定義的block引用瞭類中的實例變量,則實際上是通過self以self->instanceVar的方式引用的,這是會對self做retain操作。這樣會出現retain cycles,為瞭避免這中情況,一般會聲明一個局部變量blockSelf,將self以__block或__weak,__unsafe_unretained的方式賦值給blockSelf,在block代碼中則通過blockSelf引用類示例變量,這樣可以避免retain cycles。

        參考:
        Block Implementation Specification
        Language Specification for Blocks
        Blocks Programming Topics
        How blocks are implemented (and the consequences)
        Blocks, Episode 2: Life Cycles
        Programming with C Blocks
        Using Blocks: Understanding the Memory Management Rules
        Friday Q&A 2008-12-26 blocks
        Friday Q&A 2009-08-14: Practical Blocks
        Friday Q&A 2010-04-30: Dealing with Retain Cycles
        Friday Q&A 2011-09-30: Automatic Reference Counting
        Block的Retain Cycle的解決方法

        本文出自 清風徐來,水波不興 的博客,轉載時請註明出處及相應鏈接。

        本文永久鏈接: https://www.winddisk.com/2012/08/07/blocks/

  • 發佈留言

    發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *