代碼塊block是蘋果在iOS4開始引入的對C語言的擴展,用來實現匿名函數的特性,block是一種特殊的數據類型,其能夠正常定義變量、做爲參數、做爲返回值,特殊地,block還能夠保存一段代碼,在須要的時候調用,目前block已經普遍應用於iOS開發中,經常使用於GCD、動畫、排序及各種回調函數
block 變量的聲明格式:返回值類型(^block名字)(參數列表); //聲明一個無返回值,兩個參數的 block void(^block1)(NSString *a,NSString *b); //省略寫法 void(^block2)(NSString *,NSString *);
//block變量的賦值 //block變量名 = ^(參數列表){函數體}; block1 = ^(NSString *x,NSString *y){ NSLog(@"%@--%@",x,y); }; block1(@"123123",@"QWEQWEQWE");
//聲明 block 變量的同時進行賦值 int(^block3)(int) = ^(int a){ return a*3; }; NSLog(@"%d",block3(3));
在實際使用Block的過程當中,咱們可能須要重複地聲明多個相同返回值相同參數列表的Block變量,若是老是重複地編寫一長串代碼來聲明變量會很是繁瑣,因此咱們可使用typedef來定義Block類型動畫
#pragma mark 使用 typedef 定義 block 類型 //定義一個無返回值類型 無參數列表的 block typedef void (^Block4)(); Block4 block4 = ^(){ NSLog(@"i am block4"); }; block4();
#pragma mark block做爲函數參數 int(^block5)(int,int) = ^(int a,int b){ return a+b; }; [self useBlock5:block5]; //簡化書寫 //typedef int (^Block6)(int,int);(全局聲明) Block6 block6 = ^(int a,int b){ return a+b; }; [self useBlock6:block6]; - (void)useBlock5:(int(^)(int,int))block5 { NSLog(@"block5:%d",block5(3,5)); } - (void)useBlock6:(Block6 )block6{ NSLog(@"block6:%d",block6(4,5)); }
#pragma mark block -----------訪問局部變量 //block 中不能夠直接修改局部變量 int value1 = 100; void (^block7)(void) = ^(){ NSLog(@"value1:%d",value1); }; value1 = 200; block7();//輸出100
#pragma mark block -----------訪問局部變量 //block 中不能夠直接修改局部變量 //在局部變量前使用__block修飾,在Block中能夠直接修改局部變量 __block int value1 = 100; void (^block7)(void) = ^(){ value1++; NSLog(@"value1:%d",value1); }; value1 = 200; block7();//輸出100 __block 修飾以後輸出200
#pragma mark ------------------block 訪問全局變量 //在Block中能夠訪問全局變量 value2 = 100; void(^block8)(void) = ^(){ //在Block中能夠直接修改全局變量 self->value2++; NSLog(@"value2:%d",self->value2); }; value2 = 200; block8();
#pragma mark --------block內訪問靜態變量 static int value3 = 100; void(^block9)(void) = ^(){ value3++;//在Block中能夠直接修改靜態變量 NSLog(@"value3:%d",value3); }; //在聲明Block以後、調用Block以前對靜態變量進行修改,在調用Block時靜態變量值是修改以後的新值 value3 = 200; block9();
若是對象內部有一個Block屬性,而在Block內部又訪問了該對象,那麼會形成循環引用atom
狀況一指針
@interface Person : NSObject @property (nonatomic, copy) void(^myBlock)(); @end @implementation Person - (void)dealloc { NSLog(@"Person dealloc"); } @end Person *p = [[Person alloc] init]; p.myBlock = ^{ NSLog(@"------%@", p); }; p.myBlock(); // 由於myBlock做爲Person的屬性,採用copy修飾符修飾(這樣才能保證Block在堆裏面,以避免Block在棧中被系統釋放),因此Block會對Person對象進行一次強引用,致使循環引用沒法釋放
狀況二code
@interface Person : NSObject @property (nonatomic, copy) void(^myBlock)(); - (void)resetBlock; @end @implementation Person - (void)resetBlock { self.myBlock = ^{ NSLog(@"------%@", self); }; } - (void)dealloc { NSLog(@"Person dealloc"); } @end Person *p = [[Person alloc] init]; [p resetBlock]; // Person對象在這裏沒法正常釋放,在resetBlock方法實現中,Block內部對self進行了一次強引用,致使循環引用沒法釋放
解決循環引用的辦法是使用一個弱引用的指針指向該對象,而後在Block內部使用該弱引用指針來進行操做,這樣避免了Block對對象進行強引用對象
狀況一排序
@interface Person : NSObject @property (nonatomic, copy) void(^myBlock)(); @end @implementation Person - (void)dealloc { NSLog(@"Person dealloc"); } @end Person *p = [[Person alloc] init]; __weak typeof(p) weakP = p; p.myBlock = ^{ NSLog(@"------%@", weakP); }; p.myBlock(); // Person對象在這裏能夠正常被釋放
狀況二開發
@interface Person : NSObject @property (nonatomic, copy) void(^myBlock)(); - (void)resetBlock; @end @implementation Person - (void)resetBlock { // 這裏爲了通用一點,可使用__weak typeof(self) weakP = self; __weak Person *weakP = self; self.myBlock = ^{ NSLog(@"------%@", weakP); }; } - (void)dealloc { NSLog(@"Person dealloc"); } @end Person *p = [[Person alloc] init]; [p resetBlock]; // Person對象在這裏能夠正常被釋放