標籤:
1、關於block的循環參考:
block屬性,一般用copy修飾;
1.1.如果沒有對block進行copy操作,block就儲存於棧空間
1.2.如果對block進行copy操作,block就儲存於堆空間---強引用
1.3.如果block儲存於棧空間,不會對block內部所用到的對象產生強引用
1.4.如果block儲存於堆空間,就會對block內部所用到的對象產生強引用
注意1:由於使用了copy修飾,如果block中調用了block屬性的對象,就會造成循環參考
為了避免循環參考,需要對對象進行若引用修飾:
1 ICKPerson *p = [[ICKPerson alloc] init];2 // 1、修飾方法13 // __unsafe_unretained typeof(p) weakP = p;4 // 2、修飾方法25 __block typeof(p) weakP = p;6 p.testBlock = ^{7 [weakP run];8 };
2、關於block中變數的值:
2.1 如果變數沒有通過__block修飾,那麼block中的變數本質是值捕獲,在建立block的同時,是將變數的值傳入到block中,無論什麼時候調用,變數的值就是最初傳進去的值
1 int age = 10;2 void (^block)() = ^{ // 值捕獲3 NSLog(@"age=%d", age);// 列印是10;4 };5 age = 20;6 block();
2.2 如果變數通過__block修飾,那麼block中的變數實際傳遞的是變數的地址,在建立block的同時,是將變數的地址傳入到block中,在調用block的時候,其變數的值是當時變數的值(通過地址(指標)擷取到)。
1 __block int age = 1;2 void (^block)() = ^{ // 值捕獲3 NSLog(@"age=%d", age);// 列印是20;4 };5 age = 20;6 block();
3、關於block的內部實現:
建立block的時候,內部是建立了對應的函數;
在調用block的時候,是調用了之前封裝的函數。
4、關於block的應用:
4.1.如何定義block
1 1、// inline 2 // blockName:block變數名 3 // 傳回值類型(^變數名)(傳回值類型) 4 <#returnType#>(^blockName)(<#parameterTypes#>) = ^(<#parameters#>) { 5 <#statements#> 6 }; 7 void(^block)() = ^(){ 8 NSLog(@"block"); 9 };10 2、// name:Block類型別名11 typedef void(^MyBlock)()12 MyBlock myBlock = ^(){13 };
4.2、調用block
1 block();2 myBlock();
4.3、實戰練習:
// 4.通訊錄Block使用:
// 點擊儲存,通知連絡人重新整理表格,用代理
// block:小弟 代理:打電話
// block:先把重新整理表格的代碼儲存起來
// 等使用者點擊了儲存按鈕的時候,調用Block
4.3.1、在標頭檔中(向其他檔案中傳遞資料的檔案)定義一個block:是否帶參數,根據需求確定
1 @class ICKAddViewController,ICKContact;2 typedef void(^ICKAddViewControllerBlock)(ICKContact *contact);3 @interface ICKAddViewController : UIViewController4 @property (nonatomic, strong) ICKAddViewControllerBlock contactBlock;5 @end
4.3.2、在擷取資料後,跳轉頁面之前,調用block,將資料傳遞過去
1 - (IBAction)addcontact {2 ICKContact *contact = [ICKContact contactWithName:self.nameFiled.text andPhone:self.phoneFiled.text];3 // 調用block4 if (self.contactBlock) {5 self.contactBlock(contact);6 }7 [self.navigationController popViewControllerAnimated:YES];8 }
4.3.3、在擷取(儲存、利用)資料的檔案中(拿到擷取資料的對象的時候)調用其block屬性,儲存block程式碼片段(實現特定功能的代碼)
1 // 跳轉控制器時資料傳遞 2 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{ 3 ICKAddViewController *addVc = segue.destinationViewController; 4 // 聲明block 5 addVc.contactBlock = ^(ICKContact *contact){ 6 [self.contacts addObject:contact]; 7 8 // 儲存資料 9 NSString *cache = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];10 NSString *path = [cache stringByAppendingString:@"contacts.data"];11 [NSKeyedArchiver archiveRootObject:self.contacts toFile:path];12 [self.tableView reloadData];13 };14 }
block底層實現原理