Objective-C Block(2)

Block內部定義

我們想要知道Block的實現過程,首先我們深入Block,下圖是對Block的結構是在棧中的結構,圖片來自互聯網。

下面代碼爲對應結構體定義:

struct Block_descriptor {
    unsigned long int reserved;
    unsigned long int size;
    void (*copy)(void *dst, void *src);
    void (*dispose)(void *);
};
struct Block_layout {
    void *isa;
    int flags;
    int reserved;
    void (*invoke)(void *, ...);
    struct Block_descriptor *descriptor;
    /* Imported variables. */
};

Block_layout就是對block結構體的定義:

  • isa指針:指向表明該block類型的類。

  • flags:按bit位表示一些block的附加信息,比如判斷block類型、判斷block引用計數、判斷block是否需要執行輔助函數等。

  • reserved:保留變量,我的理解是表示block內部的變量數。

  • invoke:函數指針,指向具體的block實現的函數調用地址。

  • descriptor:block的附加描述信息,比如保留變量數、block的大小、進行copy或dispose的輔助函數指針。

  • variables:因爲block有閉包性,所以可以訪問block外部的局部變量。這些variables就是複製到結構體中的外部局部變量或變量的地址。

Block類型

從上面Block的定義Block_layout結構體中isa指針類型分爲三種:

  • _NSConcreteGlobalBlock:全局的靜態block,不訪問任何外部變量,不會涉及到任何拷貝,比如一個空的block。例如:
^{print("hello world");}
  • _NSConcreteStackBlock:保存在棧中的block,引用周圍變量,當函數返回時被銷燬。
    char a = 'A';
    ^{ print("%c\n",a); }
  • _NSConcreteMallocBlock:保存在堆中的block。該類型是由棧中Block ( Block_copy / Copy ) 複製到堆中形成的。
    //只需要加上copy就可以
    char a = 'A';
    [^{ print("%c\n",a); } copy];

需要注意的是我們一般創建的Block默認都是在棧中的,而系統的基礎數據類型也是在棧中,那麼又能使用同一個棧,倒是元素丟失,出現野指針,我們在開發中使用安全可以在定義Block時使用copy屬性遷移到棧中。

Block使用

  • 使用typedef來定義Block提高程序可讀性。
//適應typedef提高可讀性
typedef void (^ReturnTextBlock)(NSString *showText);

@interface nickNameViewController : UIViewController

@property (nonatomic, copy) ReturnTextBlock returnTextBlock;

- (void)returnText:(ReturnTextBlock)block;

@end
  • 使用安全我們定義Block使用copy屬性
@property (nonatomic, copy) ReturnTextBlock returnTextBlock;
  • 外部變量使用__block關鍵字,可在Block中修改,默認不能修改
__block int age = 0;  
void (^addAge) = ^{  
   age += 1;  
}  
NSLog(%d,age ) 
  • 避免循環引用
__block int age = 0;  
__weak id weakSelf = self;
void (^push) = ^{  
   [weakSelf push];  
}  

PS

在實際開發Block的使用非常多,作爲方法參數,比如網絡請求的失敗和成功回調,SDWebImage也同樣使用多種閉包來完成對應的功能,我記得曾經用的一個插件把Selecte做成Block也是很方便,但是在使用的時候要注意。今天在博客中介紹堆和棧並非傳統意義的堆棧,是程序在運行時在內存的分佈情況,之後我們將詳細介紹。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章