1 #import <UIKit/UIKit.h> 2 3 @interface SecondViewController : UIViewController 4 5 // 第一步:聲明屬性,用於存放傳過來的值 6 @property (nonatomic, copy) NSString *contents; 7 8 @end
1 - (void)loginButtonClick:(UIButton *)sender 2 { 3 // 建立對象 4 SecondViewController *secondVC = [[SecondViewController alloc] init]; 5 6 // 第二步:進行賦值 7 secondVC.contents = self.rootView.userTextField.text; 8 9 // 導航控制器push棧中 10 [self.navigationController pushViewController:secondVC animated:YES]; 11 }
// 第三步:顯示內容 self.nameLabel.text = self.contents;
1 #import <UIKit/UIKit.h> 2 3 #warning 第一步:在SecondViewController.h裏聲明協議 4 @protocol SecondViewControllerDelegate<NSObject> 5 6 // 聲明協議方法 7 - (void)passValueWithString:(NSString *)textString; 8 9 @end 10 11 @interface SecondViewController : UIViewController 12 13 @end
1 @interface SecondViewController : UIViewController 2 3 #warning 第二步:聲明代理人 4 5 // 代理的語義設置使用assign, 防止循環引用 6 @property (nonatomic, assign) id <SecondViewControllerDelegate> secondDelegate; 7 8 @end
聲明屬性時的語義必須是 assign , 使用 retain , copy 會致使循環引用問題 安全
1 // 實現點擊事件方法(實現代理從後往前傳值) 2 - (void)submitButtonClick:(UIButton *)sender 3 { 4 // 1.把輸入的內容傳到第一頁 5 6 #warning 第三步:使用代理調用代理的傳值方法 7 // [self.secondDelegate passValueWithString:self.eatTextField.text]; 8 9 // 判斷若是代理實現了方法進行調用(安全判斷,當沒有方法實現時不會致使程序崩潰) 10 if ([self.secondDelegate respondsToSelector:@selector(passValueWithString:)]) { 11 [self.secondDelegate passValueWithString:self.eatTextField.text]; 12 } 13 14 // 2.跳回到第一頁 15 [self.navigationController popViewControllerAnimated:YES]; 16 }
1 #warning 第四步:遵照代理協議 2 @interface FirstViewController ()<SecondViewControllerDelegate> 3 4 @property (nonatomic, strong) UILabel *myLabel; 5 6 @end
1 // 代理人的點擊事件方法(跳轉到委託方) 2 - (void)rightBarClick:(UIBarButtonItem *)sender 3 { 4 // 1.建立視圖控制器對象 5 SecondViewController *secondVC = [[SecondViewController alloc] init]; 6 7 #warning 第五步:設置代理人 8 // 指定當前對象爲代理人 9 secondVC.secondDelegate = self; 10 11 // 2.push跳轉 12 [self.navigationController pushViewController:secondVC animated:YES]; 13 }
1 #warning 第六步:實現代理方法,並接收傳過來的值 2 - (void)passValueWithString:(NSString *)textString 3 { 4 // 將傳過來的值顯示 5 self.myLabel.text = textString; 6 }
在 controller 中定義 Block , 實現 Block 的時候, 若是 Block 裏面須要使用當前控制器對象,不能夠直接使用 self , 不然會引發循環引用atom
解決辦法: spa
① 使用 __block 修飾變量防止循環引用(MRC)
代理
② 使用 __weak 修飾變量防止循環引用(ARC)指針
1 // 使用__weak修飾防止循環引用 2 // __weak SecondViewController *secodVC = self; // 通常寫法 3 4 // typeof(...) 獲得括號中的類型 5 __weak typeof(self) secodVC = self; // 裝逼寫法 6 7 self.block = ^void () { 8 NSLog(@"這事block的實現"); 9 10 secodVC.view.backgroundColor = [UIColor grayColor]; 11 };
typeof(...) 獲得括號中的類型code
方式一: 使用Block屬性實現回調傳值對象
方式二: 在方法中定義Block實現回調傳值blog
第一步: 在傳值方(SecondViewController)定義 Block 屬性事件
1 #import <UIKit/UIKit.h> 2 3 @interface SecondViewController : UIViewController 4 5 #warning 第一步:定義Block屬性 6 @property (nonatomic, copy) void(^secondBlock)(NSString *); 7 8 @end
第二步: 在接值方(FirstViewController) 跳轉到委託方的點擊事件實現方法中 實現Block, 即Block回調內存
1 // 跳轉點擊事件實現方法 2 - (void)barClick:(UIBarButtonItem *)sender 3 { 4 SecondViewController *secondVC = [[SecondViewController alloc] init]; 5 6 #warning 第二步 實現Block 7 // Block回調 8 secondVC.secondBlock = ^void (NSString *string) { 9 // 獲得Block回傳的string,並賦值給myLabel 10 self.myLabel.text = string; 11 }; 12 13 [self.navigationController pushViewController:secondVC animated:YES]; 14 }
第三步: 在傳值方(SecondViewController)的返回點擊事件中, 調用Block實現傳值
1 // 實現方法 進行Block傳值 2 - (void)submitButtonClick:(UIButton *)sender 3 { 4 // 1.Block傳值 5 6 #warning 第三步 Block傳值, 調用Block 7 self.secondBlock(self.textField.text); 8 9 // 2.返回第一頁 10 [self.navigationController popViewControllerAnimated:YES]; 11 }
① 沒有使用局部變量的 Block 內存存儲在全局區
② 使用局部變量的 Block 內存存儲在 棧區
③ 當 Block 變量定義爲屬性的時候, 必須使用 copy 修飾, retain無效, 即 retain 和 assign 會形成野指針問題
當對 Block 進行 copy 操做的時候, 此時 Block 的內存區域爲 堆區
當不使用 Block 時須要使用 Block_Release() 進行銷燬