使用storyboard實現頁面跳轉,簡單的數據傳遞(轉載)

原文地址

 由於最近才接觸到IOS,蘋果已經建議storyboard來搭建所有界面了,於是我也追隨時尚,直接開始使用storyboard。(不料在涉及到頁面跳轉的時候,遇到的問題是:點擊後沒有任何反應)衆所周知,在storyboard中,界面的跳轉是通過segue來實現的,利用它,省去了方法內寫入跳轉的代碼。


一 視圖跳轉

《StoryBoard下的視圖跳轉》

我們知道:segue共有三種類型:push,modal,和custom。如下圖://01


簡單說下這三個的作用:使用導航欄壓進新的控制器(push),模態的加載視圖控制器(modal),自定義(custom)。

好了,廢話少說,現在開始我們的旅行。

1,首先建立一個Single View 模板的項目,記得勾選上storyboard。然後打開它,在rootViewController(也就是我們的主視圖)添加一些label和一個button。

2,在右邊的庫中拖入一個ViewController,也添加一個Label。具體如下圖所示://02


3,選中button,右鍵(或control+鼠標左鍵)拖拽到第二個ViewController中,選擇:Modal,然後記得save。這個時候,運行模擬器,點擊button,你會發現成功跳轉到了第二個界面。我們沒有在代碼區做任何操作,甚至連button和第二個ViewController都沒有創建,確實就是這麼的簡單。//03


好了,到了這裏,簡單說一下storyboard下,利用segue界面跳轉一共有兩種方式:

第一種就是以上我的例子,利用button組件,拖拽添加segue,直接運行就可以用。

第二種是利用ViewController與ViewController之間,拖拽添加segue。不過,這種方法就需要在相應需要跳轉的方法內寫入代碼,手動去設置它的跳轉。

4,把剛纔例子設置button的segue刪除(右鍵,點X),一切恢復了最初時的狀態,我們給buttom添加一個點擊的方法,然後在ViewController.m中實現此方法,在方法體內寫入這樣的代碼://04


5,注意看方法參數:@"second",這個second是我自命名的一個標示符,一會你就會遇到。

6,save保存,打開storyboard,選中rootViewController,右鍵拖拽到第二個ViewController,在彈出的界面同樣選擇:modal。//05


7,打開這個segue的設置頁面:設置其identifier爲second,就是我在代碼中的那個自命名參數。

8,save保存,運行模擬器,你會驚奇的發現,實現了同樣的跳轉。

到現在爲止,我們一共用兩種簡單的方式實現了視圖的跳轉:1是設置button的segue,2是設置viewcontroller與viewcontroller之間的segue,只是後者需要在代碼中手動管理跳轉。

看似很簡單的事情,卻讓我耽誤一些時間,主要是因爲我在網上看的好多例子都是以UINavigationController爲rootviewController(這樣省事省時,跳轉後還可以利用系統爲我們創建的返回按鈕返回到rootViewController),然後用button拖拽到第二個視圖時選擇的push,由於當時不理解push相關的類型含義,所以在寫的時候,我總是選擇push,造就了點擊後無法跳轉。現在終於明朗了,記錄下來,供不明白的同學學習。

----------------------------------------------------------------------------------------------------

 //根據 segue Identifier跳轉界面

    [self performSegueWithIdentifier:@"GotoTwo" sender:self];

    

   //modal 方式跳轉

    [self presentModalViewController:nil animated:YES];

    

   //壓進一個viewcontroller

    [self.navigationController pushViewController:nil animated:YES];


   //彈出一個viewcontroller  相當與返回上一個界面

    [self.navigationController popViewControllerAnimated:YES];

    

   //  modal跳轉的返回方法

    [self dismissModalViewControllerAnimated:YES];

-----------------------------------------------------------------------------------------------------

再寫一下關於segue三個類型的詳解:

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

在storyboard中,segue有幾種不同的類型,在iphone和ipad的開發中,segue的類型是不同的。
在iphone中,segue有:push,modal,和custom三種不同的類型,這些類型的區別在與新頁面出現的方式。
而在ipad中,有push,modal,popover,replace和custom五種不同的類型。
 
 
modal 
最常用的場景,新的場景完全蓋住了舊的那個。用戶無法再與上一個場景交互,除非他們先關閉這個場景。
是在viewController中的標準切換的方式,包括淡出什麼的,可以選切換動畫。
Modalview:就是會彈出一個view,你只能在該view上操作,而不能切換到其他view,除非你關閉了modalview.
Modal View對應的segue type就是modal segue。
*Modal:Transition to another scene for the purposes of completing a task.當user在彈出的modalview裏操作完後,就應該dismiss the modal view scene然後切換回the originalview.
 

push
Push類型一般是需要頭一個界面是個Navigation Controller的。
是在navigation View Controller中下一級時使用的那種從右側劃入的方式
*Push:Create a chain of scenes where the user can move forward or back.該segue type是和navigation viewcontrollers一起使用。
 
popover(iPad only)
popover 類型,就是採用浮動窗的形式把新頁面展示出來
*Popover(iPad only):Displays the scene in a pop-up “window” over top of the current view.
 
Replace (iPad only):
替換當前scene,
Replace the current scene with another. This is used in some specialized iPad viewcontrollers (e.g. split-view controller).
 
custom
就是自定義跳轉方式啦。
*Custom:Used for programming a customtransition between scenes.
在Storyboard中使用自定義的segue類型

參考http://ryan.easymorse.com/?p=72

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

《Xib下的視圖跳轉》

現在說一下,沒有使用Storyboard,直接創建xib時的頁面跳轉,其實也很簡單,只要理解了,都不是問題。我也是從java剛轉過來,起初感覺很不適應,但是現在發現interface builder真的是太強大了。


1,創建一個項目,我用的是Empty Application模版,這種模版創建出來的項目只包含一個Appdelegate.h和Appdelegate.m文件,rootviewController需要我們自行創建。(注意:最新的版本,apple把MainWindow.xib文件取消了,所以無法打開xib查看包含的圖標)此時運行模擬器只會顯示空白的界面。好了,File-newFile 創建一個Object-C class,打開後,subclass of 選擇默認的UIViewController,注意,需要勾選上With XIB for user interface,不然一會無法創建主視圖。


2,創建好後,打開其xib文件,簡單添加一些button組件。此時保存運行程序還是無法顯示我們創建的RootViewController。【有時如果你在項目清單下的user interface 選擇此MainViewController運行後臺還會報:Applications are expected to have a root view controller at the end of application launch的錯誤,原因都是項目的Delegate無法發現一個rootViewContrller】所以這就需要我們手動在AppDelegate中讓它們關聯起來。

AppDelegate.h


AppDelegate.m


[self.viewController就是我們在.h文件中聲明的]


3,好了,保存後,這個時候運行就能顯示我們的界面了~同樣也很簡單吧!好了,我們現在參照以上的方法,再創建一個SecondViewController(記得勾選xib),然後我們給rootviewcontroller視圖的 button添加一個事件方法,可以讓它點擊後跳轉到SecondViewController。


(首先創建了一個SecondViewController並實例化,intitWithNibName的參數一定要正確寫控制器配對的xib文件的名稱,調用presentModalViewController:controller 就可以跳轉啦。)


發現了把,其實都挺簡單的,本來可以創建single View Application模板的,這樣就省去創建rootViewController和在Delegate中寫那些代碼了,我這樣也就是讓大家感受一下,xib,delagate,stroyboard之間的區別和聯繫,都嘗試一下,你們就會明白他們之間的機制,至少可以會寫界面和跳轉的方法啦。哈哈,有什麼問題大家一起交流,我也是初學者,可以給我留言噢。~~~




二 頁面傳值


方法一使用segue傳遞數據,繼續上面的項目例子。

1,在rootViewController聲明一個UITextField並與storyboard關聯上。File-add添加一個SecondViewController(繼承UIViewController),然後在keyboard第二個viewcontroller的屬性設置其class關聯。同樣在SecondViewController聲明一個UITextField並關聯。如圖所示://06


2,然後在rootViewController.m的文件中覆蓋名稱爲:prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender的方法,並寫入如下語句,如圖://07


3,我們獲取了主視圖的文本框內容,並通過segue的方法發送了出去,接下來要做的就是在secondViewController聲明一個@property NSString * 類型,名稱爲data的字符串,然後在其.m文件中的-(void) viewDidLoad方法中寫入如下代碼://08


注意:發送數據時,[send setValue:msg forKey:@"data"]; 這個"data"名稱一定要與跳轉後界面的聲明的類型對象的命名一致,不然的話,跳轉後的界面是收不到傳遞的值的。




方法二,使用notification廣播實現視圖跳轉傳遞數據,繼續上面的項目展開。


廣播機制分爲:註冊----發送------------接收(接收方),具體請看一下代碼。

1,在要發送數據的視圖頁面.m文件處理髮送邏輯的方法裏註冊+發送

[java] view plaincopy
  1. - (IBAction)pressed:(id)sender {  
  2.       
  3. //    [self performSegueWithIdentifier:@"second" sender:self];  
  4.     NSLog(@"send message:%@",firstField.text);  
  5.   
  6.       
  7.       
  8.     //頁面跳轉傳值方法二:利用notification  
  9.     NSDictionary *dicts = [NSDictionary dictionaryWithObjectsAndKeys:@"one1",@"one",@"two2",@"two",@"three3",@"three", nil];  
  10.     //註冊(第一步)  
  11.     NSNotification *notification  =[NSNotification notificationWithName:@"mynotification" object:firstField.text];  
  12.     //發送(第二步)  
  13.     [[NSNotificationCenter defaultCenter] postNotification:notification];  
  14.       
  15.     //註冊+發送也可以一行完成(等效於以上兩行)  
  16.     [[NSNotificationCenter defaultCenter] postNotificationName:@"mynotification2" object:dicts];//發送一個字典過去  
  17.   
  18.   
  19. }  
notificationWithName:參數的值是自己定義,接收方以此名稱爲接收標識。

2,在跳轉後,接收數據視圖頁面.m文件中處理邏輯的方法裏 接收

[java] view plaincopy
  1. - (void)viewDidLoad  
  2. {  
  3.     [super viewDidLoad];  
  4.     // Do any additional setup after loading the view.  
  5.       
  6.     //接受端:接受(第一步)  
  7.     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationHandler:) name:@"mynotification" object:nil];  
  8.       
  9.       
  10.     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationHandler2:) name:@"mynotification2" object:nil];  
  11.   
  12. }  
  13.   
  14. //自定義接收信息和處理的方法(第二步)  
  15. -(void) notificationHandler:(NSNotification *) notification{  
  16.       
  17.     secondField.text = [notification object];//收到消息後在UItextField中顯示出來  
  18.   
  19. }  
  20. //自定義接收字典信息的方法  
  21. -(void) notificationHandler2:(NSNotification *) notification2{  
  22.   
  23.     NSDictionary *dict = [notification2 object];  
  24.      NSLog(@"receive dict :%@,forkey:%@",dict,[dict objectForKey:@"one"]);  
  25.   
  26. }  

注意:如果註冊的notification在目標視圖沒有收到或名稱寫錯,目標視圖的相關方法就不會執行

國外參考論壇【傳送門】http://blog.isotoma.com/2009/11/on-objective-c-delegates-and-nsnotification-objects/

方法三,通過Delegate委託傳遞數據

此方法我測試完後,感覺不是太好用,有一些侷限性,相當於自定義讀取方法:無非是在A對象裏保存了一個B對象的指針,然後在A的某個函數裏去設置B對象某個屬性的值。

具體看教程把。

1,首先add a File--  Objective-C protocol,然後聲明一個傳遞數值的方法:

[java] view plaincopy
  1. //<1>自定義一個用來傳遞數值的delegate  
  2. @protocol ViewPassValueDelegate <NSObject>  
  3.   
  4.   
  5. -(void) passValue :( NSString *) value;  
  6.   
  7.   
  8.   
  9. @end  

2,然後在要發送數據的視圖的.h文件下聲明一個自定義的delegate

[java] view plaincopy
  1. #import <UIKit/UIKit.h>  
  2. #import "ViewPassValueDelegate.h"  
  3.   
  4.   
  5. @interface ViewController : UIViewController{  
  6.   
  7.     NSObject<ViewPassValueDelegate> *delegte ;  
  8.   
  9. }  
  10.   
  11.   
  12. - (IBAction)pressed:(id)sender;//主視圖button點擊出發的Action  
  13. @property (retain, nonatomic) IBOutlet UITextField *firstField;  
  14.   
  15.   
  16.   
  17. @end  

3,在要發送數據的視圖的事件處理方法裏聲明一個secondViewController實例,然後賦值給 delegate,同時執行協議的 passValue方法

[java] view plaincopy
  1. - (IBAction)pressed:(id)sender {  
  2.       
  3.     secondViewController *secondController = [[secondViewController alloc] init];//實例化一個視圖2的對象  
  4.     delegte =  secondController;  
  5.     [delegte passValue:firstField.text];  
  6.       
  7.   
  8. }  

4,然後在接收數據視圖(secondViewController).h文件實現自定義協議

[java] view plaincopy
  1. //<2> 視圖1實現自定義協議  
  2. @interface secondViewController : UIViewController<ViewPassValueDelegate>  

5,在接收數據視圖(secondViewController).m文件中實現協議中的passValue方法:

[java] view plaincopy
  1. //<3>實現自定義delege的方法  
  2. -(void) passValue:(NSString *)value{  
  3.   
  4.   
  5.     secondField.text= value;  
  6.     NSLog(@"passValue method get Value : %@ secondField.text:%@",value,secondField.text);  
  7.   
  8.   
  9. }  


至此,大功告成,打印輸出會顯示你在第一個界面發送的數據,但是我把此數據賦值於頁面的UITextField對象,但是此對象得到的值總是null,無法在界面展示出來,我也很苦惱,什麼方法都嘗試完了,發現此接收方法總是會在ViewDidLoad方法之後執行,並且方法體內設置UITextField任意值都無法成功。

目前總結是,以上value只是對視圖1對象賦值時的一個指針引用,出了方法範圍,就無效了。所以在方法體內打印都是有數據的,出了方法體,就沒有持有的引用了。


具體原因有待考察。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章