iOSDay27之界面通訊

1. 屬性傳值(前面的界面給後面傳值)

 第一步: 在 SecondViewController.h 文件裏定義一個存放傳過來值的變量 contents

1 #import <UIKit/UIKit.h>
2 
3 @interface SecondViewController : UIViewController
4 
5 // 第一步:聲明屬性,用於存放傳過來的值
6 @property (nonatomic, copy) NSString *contents;
7 
8 @end

 第二步: 在 FirstViewController按鈕點擊方法裏給 SecondViewController 的 contents 屬性賦值

 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 }

 第三步: SecondViewController 將傳過來的值顯示, 使用 contents 屬性給 nameLabel 賦值(在 viewDidLoad 中)

// 第三步:顯示內容
self.nameLabel.text = self.contents;

2. 協議傳值(後面的界面給前面傳值)

 第一步: 聲明協議(在委託方(SecondViewController)的 .h 文件中聲明)

 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

 第二步: 聲明代理人(在委託方(SecondViewController)的 .h 文件中聲明代理人, 代理人是一個屬性)

1 @interface SecondViewController : UIViewController
2 
3 #warning 第二步:聲明代理人
4 
5 // 代理的語義設置使用assign, 防止循環引用
6 @property (nonatomic, assign) id <SecondViewControllerDelegate> secondDelegate;
7 
8 @end

聲明屬性時的語義必須是 assign , 使用 retain , copy 會致使循環引用問題 安全

 第三步: 執行協議方法(委託方(SecondViewController)在點擊事件中使用代理屬性調用代理的傳值方法)

 

 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 }

 第四步: 簽定協議(代理人(FirstViewController)遵照協議)

1 #warning 第四步:遵照代理協議
2 @interface FirstViewController ()<SecondViewControllerDelegate>
3 
4 @property (nonatomic, strong) UILabel *myLabel;
5 
6 @end

 第五步: 指定代理人(在代理人(FirstViewController) 跳轉到委託方的點擊事件方法指定)

 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 }

 第六步: 實現協議方法(代理人(FirstViewController)實現代理方法, 並接收傳過來的值顯示)

1 #warning 第六步:實現代理方法,並接收傳過來的值
2 - (void)passValueWithString:(NSString *)textString
3 {
4     // 將傳過來的值顯示
5     self.myLabel.text = textString;
6 }

3. Block傳值

 1> 回顧Block

 2> Block注意事項

  在 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

 3> Block傳值的兩種方式

  方式一: 使用Block屬性實現回調傳值對象

  方式二: 在方法中定義Block實現回調傳值blog

 4> Block屬性傳值

  第一步: 在傳值方(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 }

 5> 在方法中定義Block傳值

 

 6> Block存儲域

  ① 沒有使用局部變量Block 內存存儲在全局區

  ② 使用局部變量的 Block 內存存儲在 棧區

  ③ 當 Block 變量定義爲屬性的時候, 必須使用 copy 修飾, retain無效, 即 retainassign形成野指針問題

  當對 Block 進行 copy 操做的時候, 此時 Block 的內存區域爲 堆區

  當不使用 Block 時須要使用 Block_Release() 進行銷燬

相關文章
相關標籤/搜索