iOS開發中視圖控制器ViewControllers之間的數據傳遞

iOS開發中視圖控制器ViewControllers之間的數據傳遞

這裏咱們用一個demo來講明ios是如何在視圖控制器之間傳遞重要的參數的。本文先從手寫UI來討論,在下一篇文章中討論在storyboard中傳遞數據。html

首先新建一個空工程,並添加一個根視圖控制器類,以下圖所示:java

\#ios

在函數didFinishLunchingWithOption中添加幾行代碼,完成後以下:app

 

?
1
2
3
4
5
6
7
8
9
10
11
12
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
     self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
     // Override point for customization after application launch.
     self.window.backgroundColor = [UIColor whiteColor];
     [self.window makeKeyAndVisible];
     
     RootViewController *myRootViewController = [[RootViewController alloc] init];
     myRootViewController.view.backgroundColor = [UIColor lightGrayColor];
     self.window.rootViewController = myRootViewController;
     return YES;
}


完成之後運行,iOS模擬器顯示結果以下:ide

 

\#函數

由圖中能夠看出,咱們自定義的myRootViewController已經成功在啓動時加載,顯示出了一個淺灰色的界面。post

隨後如法炮製新建另外一個viewController命名爲FirstSubViewController,同時在RootViewController的viewDidLoad函數中添加以下代碼:atom

 

?
1
2
3
4
5
6
7
8
9
10
- ( void )viewDidLoad
{
     [ super viewDidLoad];
     // Do any additional setup after loading the view.
     UIButton *firstVC = [UIButton buttonWithType:UIButtonTypeSystem];
     firstVC.frame = CGRectMake( 60 , 244 , 200 , 80 );
     [firstVC setTitle:@ "顯示下一個視圖" forState:UIControlStateNormal];
     [firstVC addTarget:self action: @selector (displayNextViewController) forControlEvents:UIControlEventTouchUpInside];
     [self.view addSubview:firstVC];
}

以後還需定義一個函數,名爲displayNextViewController,函數體暫時設爲空。此時運行程序,界面中央將顯示一個按鈕「顯示下一個視圖」,可是單擊該按鈕沒有任何反應。這是由於響應函數displayNextViewController尚未實現。如今在該函數中添加代碼:spa

 

 

?
1
2
3
4
5
6
7
- ( void )displayNextViewController
{
     FirstSubViewController *firstSubVC = [[FirstSubViewController alloc] init];
     [self presentViewController:firstSubVC animated:YES completion:^{
         NSLog(@ "present first sub VC ok" );
     }];
}


完成後運行程序發現,按鈕已經有反應了,按下後回出現一個新的白色背景的新界面,這就是咱們在這裏定義的firstSubVC;代理

 

 

下一步實現界面的返回操做。在FirstSubViewController的viewDidLoad函數中創建一個回退按鈕,並實現其響應函數。代碼以下:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- ( void )viewDidLoad
{
     [ super viewDidLoad];
     // Do any additional setup after loading the view.
     
     UIButton *goBack = [UIButton buttonWithType:UIButtonTypeSystem];
     goBack.frame = CGRectMake( 60 , 244 , 200 , 80 );
     [goBack setTitle:@ "返回上級界面" forState:UIControlStateNormal];
     [goBack addTarget:self action: @selector (goBackToPreviousViewController) forControlEvents:UIControlEventTouchUpInside];
     [self.view addSubview:goBack];
}
 
- ( void )goBackToPreviousViewController
{
     [self dismissViewControllerAnimated:YES completion:^{
         NSLog(@ "Back to previous OK" );
     }];
}


到此爲止,咱們已經經過presentViewController和dismissViewController實現了視圖的切換,下面來考慮兩個視圖控制器之間的數據交流的問題。

 

在此以前,分別在RootViewController和FirstSubViewController中添加一個標籤和文本框,做爲數據的顯示和輸入部分。咱們的目的是在FirstSubViewController中輸入一個數字,而後再RootViewController顯示出來。

在這兩個類中分別用property來實現文本框和標籤欄:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//RootViewController.m
@interface RootViewController ()
 
@property (strong,nonatomic) UILabel *lable;
 
@end
 
@implementation RootViewController
 
- (UILabel *)lable
{
     if (!_lable)
     {
         _lable= [[UILabel alloc] initWithFrame:CGRectMake( 60 , 150 , 200 , 30 )];
         _lable.textAlignment = NSTextAlignmentCenter;
         _lable.text = @ "Hello World!" ;
         _lable.backgroundColor = [UIColor whiteColor];
     }
     return _lable;
}
…..
@end
 
//FirstSubViewController
@interface FirstSubViewController ()
 
@property (strong,nonatomic) UITextField *inputText;
 
@end
 
@implementation FirstSubViewController
 
- (UITextField *)inputText
{
     if (!_inputText)
     {
         _inputText = [[UITextField alloc] initWithFrame:CGRectMake( 60 , 150 , 200 , 30 )];
         _inputText.backgroundColor = [UIColor lightGrayColor];
     }
     return _inputText;
}
…..
@end



 

在這兩個視圖控制器的viewDidLoad中分別添加以下代碼:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//RootViewController.m
- ( void )viewDidLoad
{
     [ super viewDidLoad];
     // Do any additional setup after loading the view.
     [self.view addSubview:self.label];
     
     UIButton *firstVC = [UIButton buttonWithType:UIButtonTypeSystem];
     …..
}
…..
//FirstSubViewController
- ( void )viewDidLoad
{
     [ super viewDidLoad];
     // Do any additional setup after loading the view.
     
     //添加輸入框
     [self.view addSubview:self.inputText];
     UIButton *goBack = [UIButton buttonWithType:UIButtonTypeSystem];
     …..
}

 

 

在視圖控制器之間進行數據傳遞能夠經過多種方法,下面將逐個實驗:

一、使用代理delegate的方法:

基本原理:FirstSubViewControllers試圖改變RootViewController的數據,可是除了操做本身內部的數據的能力以外,不能改變其餘類的數據。想要將這些數據傳遞出去,須要設置代理方法,獲取FirstSubViewControllers中數據的類來遵循該方法,經過實現該代理協議中的方法來獲取FirstSubViewControllers中的數據。

具體步驟:

首先在FirstSubViewController.h中定義協議:

 

?
1
2
3
4
5
6
@protocol FirstSubViewControllerDelegate <nsobject>
 
@optional
- ( void )getStringFromFirstSubViewControllerDelegate:(NSString *)outputString;
 
@end </nsobject>


而後添加一個符合該協議的代理屬性:

 

 

?
1
2
@property (nonatomic,weak) id<firstsubviewcontrollerdelegate> delegate;
</firstsubviewcontrollerdelegate>


在RootViewControlller.h中,聲明該類符合FirstSubViewControllerDelegate協議:

 

 

?
1
@interface RootViewController : UIViewController<firstsubviewcontrollerdelegate></firstsubviewcontrollerdelegate>


在新建FirstSubViewController的實例後,將其delegate屬性定義爲self,同時實現協議中的方法,兩個函數以下:

 

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
- ( void )getStringFromFirstSubViewControllerDelegate:(NSString *)outputString
{
     self.lable.text = outputString;
}
 
- ( void )displayNextViewController
{
     FirstSubViewController *firstSubVC = [[FirstSubViewController alloc] init];
     firstSubVC.delegate = self;
     [self presentViewController:firstSubVC animated:YES completion:^{
         NSLog(@ "present first sub VC ok" );
     }];
}


最後在FirstSubViewController.m的goBackToPreviousViewController中添加一句向delegate屬性發送獲取數據的消息:

 

 

?
1
2
3
4
5
6
7
- ( void )goBackToPreviousViewController
{
     [self.delegate getStringFromFirstSubViewControllerDelegate:self.inputText.text];
     [self dismissViewControllerAnimated:YES completion:^{
         NSLog(@ "Back to previous OK" );
     }];
}

 

 

這樣,大功告成了,在FirstSubViewController中的輸入框中輸入的內容,在按返回按鈕後回顯示在第一個界面的標籤上。

 

二、使用通知Notification的方法

關於通知的知識在將來將會詳述,在這裏只是簡要介紹一種使用通知這一機制的方法。

在使用通知以前,必須在默認通知中內心添加一個所謂「觀察者」和通知,這個通知是命名的,同時還指定了回調的方法。當該通知中心收到了某個對象發送了相應的通知時,將會調用指定的方法執行某項操做。通知的發送者同時還能夠發送相應的消息做爲通知的參數。

註冊通知中心能夠在RootViewController.m中的viewDidLoad函數的末尾添加以下函數:

 

?
1
2
//使用通知的方式實現
[[NSNotificationCenter defaultCenter] addObserver:self selector: @selector (changeLabelText:) name:@ "ChangeLabelTextNotification" object:Nil];

此外還要實現觀察者的回調函數:

 

 

?
1
2
3
4
5
- ( void )changeLabelText:(NSNotification *)notification
{
     id text = notification.object;
     _lable.text = text;
}

自此通知的接收端已經完成。

 

通知的發送端,只需在「返回上級界面」的相應函數中按照事先定義的名稱發送通知和參數便可:

 

?
1
2
//使用通知方式實現
[[NSNotificationCenter defaultCenter] postNotificationName:@ "ChangeLabelTextNotification" object:_inputText.text];

此時運行,將會發現和代理模式起到了相同的做用。

 

除了代理和通知以外,還有其餘如KVO等方法,將來還會詳細探討。

相關文章
相關標籤/搜索