1. 程式人生 > >【iOS介面處理】使用storyboard實現頁面跳轉,簡單的資料傳遞

【iOS介面處理】使用storyboard實現頁面跳轉,簡單的資料傳遞

http://blog.csdn.net/mad1989/article/details/7919504

        由於最近才接觸到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檔案處理髮送邏輯的方法裡註冊+傳送

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

2,在跳轉後,接收資料檢視頁面.m檔案中處理邏輯的方法裡 接收

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

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

方法三,通過Delegate委託傳遞資料

此方法我測試完後,感覺不是太好用,有一些侷限性,相當於自定義讀取方法:無非是在A物件裡儲存了一個B物件的指標,然後在A的某個函式裡去設定B物件某個屬性的值。

具體看教程把。

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

  1. //<1>自定義一個用來傳遞數值的delegate
  2. @protocol ViewPassValueDelegate <NSObject>  
  3. -(void) passValue :( NSString *) value;  
  4. @end

2,然後在要傳送資料的檢視的.h檔案下宣告一個自定義的delegate

  1. #import <UIKit/UIKit.h>  
  2. #import"ViewPassValueDelegate.h"
  3. @interface ViewController : UIViewController{  
  4.     NSObject<ViewPassValueDelegate> *delegte ;  
  5. }  
  6. - (IBAction)pressed:(id)sender;//主檢視button點擊出發的Action
  7. @property (retain, nonatomic) IBOutlet UITextField *firstField;  
  8. @end

3,在要傳送資料的檢視的事件處理方法裡宣告一個secondViewController例項,然後賦值給 delegate,同時執行協議的 passValue方法
  1. - (IBAction)pressed:(id)sender {  
  2.     secondViewController *secondController = [[secondViewController alloc] init];//例項化一個檢視2的物件
  3.     delegte =  secondController;  
  4.     [delegte passValue:firstField.text];  
  5. }  

4,然後在接收資料檢視(secondViewController).h檔案實現自定義協議
  1. //<2> 檢視1實現自定義協議
  2. @interface secondViewController : UIViewController<ViewPassValueDelegate>  

5,在接收資料檢視(secondViewController).m檔案中實現協議中的passValue方法:
  1. //<3>實現自定義delege的方法
  2. -(void) passValue:(NSString *)value{  
  3.     secondField.text= value;  
  4.     NSLog(@"passValue method get Value : %@ secondField.text:%@",value,secondField.text);  
  5. }  


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

目前總結是,以上value只是對檢視1物件賦值時的一個指標引用,出了方法範圍,就無效了。所以在方法體內列印都是有資料的,出了方法體,就沒有持有的引用了。

具體原因有待考察。