[iOS7的一些總結]2、視圖控制器ViewControllers之間的資料傳遞(1)

來源:互聯網
上載者:User

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

首先建立一個空工程,並添加一個根視圖控制器類,如所示:

#

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

 

- (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模擬器顯示結果如下:

 

#

由圖中可以看出,我們自訂的myRootViewController已經成功在啟動時載入,顯示出了一個淺灰色的介面。

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

 

- (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還沒有實現。現在在該函數中添加代碼:

 

 

- (void)displayNextViewController{    FirstSubViewController *firstSubVC = [[FirstSubViewController alloc] init];    [self presentViewController:firstSubVC animated:YES completion:^{        NSLog(@"present first sub VC ok");    }];}

完成後運行程式發現,按鈕已經有反應了,按下後回出現一個新的白色背景的新介面,這就是我們在這裡定義的firstSubVC;

 

 

下一步實現介面的返回操作。在FirstSubViewController的viewDidLoad函數中建立一個回退按鈕,並實現其響應函數。代碼如下:

 

- (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來實現文字框和標籤欄:

 

//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中分別添加如下代碼:

 

//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];    …..}

 

在視圖控制器之間進行資料傳遞可以通過多種方法,下面將逐個實驗:

1、使用代理delegate的方法:

基本原理:FirstSubViewControllers試圖改變RootViewController的資料,但是除了操作自己內部的資料的能力之外,不能改變其他類的資料。想要將這些資料傳遞出去,需要設定代理方法,擷取FirstSubViewControllers中資料的類來遵循該方法,通過實現該代理協議中的方法來擷取FirstSubViewControllers中的資料。

具體步驟:

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

 

@protocol FirstSubViewControllerDelegate @optional- (void)getStringFromFirstSubViewControllerDelegate:(NSString *)outputString;@end

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

 

 

@property (nonatomic,weak) id delegate;

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

 

 

@interface RootViewController : UIViewController

在建立FirstSubViewController的執行個體後,將其delegate屬性定義為self,同時實現協議中的方法,兩個函數如下:

 

 

- (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屬性發送擷取資料的訊息:

 

 

- (void)goBackToPreviousViewController{    [self.delegate getStringFromFirstSubViewControllerDelegate:self.inputText.text];    [self dismissViewControllerAnimated:YES completion:^{        NSLog(@"Back to previous OK");    }];}

 

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

 

2、使用通知Notification的方法

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

在使用通知之前,必須在預設通知中樞裡添加一個所謂“觀察者”和通知,這個通知是命名的,同時還指定了回調的方法。當該通知中樞收到了某個對象發送了相應的通知時,將會調用指定的方法執行某項操作。通知的寄件者同時還可以發送相應的訊息作為通知的參數。

註冊通知中樞可以在RootViewController.m中的viewDidLoad函數的末尾添加如下函數:

 

//使用通知的方式實現[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(changeLabelText:) name:@"ChangeLabelTextNotification" object:Nil];
此外還要實現觀察者的回呼函數:

 

 

- (void)changeLabelText:(NSNotification *)notification{    id text = notification.object;    _lable.text = text;}
自此通知的接收端已經完成。

 

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

 

    //使用通知方式實現    [[NSNotificationCenter defaultCenter] postNotificationName:@"ChangeLabelTextNotification" object:_inputText.text];
此時運行,將會發現和代理模式起到了相同的作用。

 

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

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.