2011年10月28日 星期五

View Controller (NSObject) 之間交換資料 by Segue

延續上一篇有關 Storyboard 的簡介,現在我們要來介紹在 Storyboard 中看到的新角色 Segue。
首先我們先來秀一下 Segue 的威力。在 MyFirst5 的專案中,再新增一個 View Controller 這樣總共有兩個 View Controller 然後各在其上拉一個 UILabel 做為識別,並在 Initial View Controller 的 View 上方,放置一個 UIButton 如下圖所示。
接下來我們要做一件很直覺的事情,就是按著 Ctrl 然後從 Hello Story 的 Button Click Drag 到右邊的 Second 畫面。放開之後你會看到如下的選擇畫面。選 Modal
接著會看到新的角色出現。Segue 。如下圖
 Segue 查字典是指動詞,流暢地轉換。也可以想像它是一個過場效果。OK 就這樣。直接執行。然後按下 Show Button 你將會看到 Magic 產生。從下方的畫面。
 產生如下的畫面,其過場動畫就是 Modal View Controller 呈現的效果。
產生這個 Modal View 我們沒有寫任何的程式碼,這個就是 Segue 迷人的地方。接著要更進一步來利用 Segue. 在 MyStory.storyboard 在 Second 新增一個 Text Field 和 Button 如下畫面。
接著我想要把左邊的 Label : Hello Story 這個字樣,傳到右邊的 Text Field 上面,時間點就是按下 Show 這個按鈕的時候。不過,這個時候有一個大問題,產生這兩個 View Controller 的物件是由 Storyboard 產生的而且他們的 Class 是 UIViewController,換句話說,我們沒辦法去更動 UIViewController 內容,因為我們沒有 UIViewController.m 的原始碼。但我們可以繼承它,然後把上面兩個 View Controller 的 Class 都改成我們新增的 Class。新先增兩個 Class 都繼承自 UIViewController 各命名為 HelloController 和 SecondController。首先新增 HelloController 如下的設定

不需要產生 Xib 檔,因為 Storyboard 就提供了和 Xib 檔相當的功能。其實 Stroyboard 就是很多個 Xib 檔的組合。成功產生之後會在 Navigator 看到。如下的畫面。
然後點選 Storyboard 的 Initial View Controller 的 View Controller 圖形,把它的 Class 改成 HelloController。如下圖
相同的做法產生 SecondController 如下圖。
接著也改掉 Storyboard 中 Second 的 View Controller 圖示的 Class 成 SecondController. 如下圖。
OK 材料都準備齊了。再來思考剛剛的問題。我們要從左邊 View Controller 傳資料給右邊的 View Controller。也就是由 HelloController 的實體,傳給 SecondController 的實體,傳遞的方向和 Segue 一樣,我們要在 SecondController (接受端) 新增 propery 來接 HelloController (傳送端) 傳來的資料。於是我們在 SecondController.h 新增 property dataString 而且要新增一個 IBOutlet 用來指向 Storyboard 上 SecondController 畫面上的 Text Field 實體。如下所示。
 記得各都要有 @Synthesize 在 .m 。然後上方的小圈圈中間有個黑實圈表示和 Storyboard 的圖示連在一起了。接著我們要思考一件事,在這我們用  dataString 來接受資料,要在什麼時候放到 inputField 上面呢?在 viewDidLoad。所以在 SecondController.m 的 viewDidLoad 如下表示。

現在接受端準備好了,傳送端要如何傳送呢?直覺的想就是程式碼要寫在 HelloController 裡。的哪?介紹一個新的 method。
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
這個method 會在 segue 在呼叫起 View Controller 之前被呼叫,我們來看看要寫什麼?
在 line 60,我們可以用 segue 的  destinationViewController 就可以拿到執行中 SecondController 的實體。然後把 @"From Hello" 傳給 SecondController 的 property dataString 。執行之後,按下按鈕,你會看到如下畫面。
From Hello 傳到 Text Field 上面了。Good。但好像不是我們要的。我們想把 Hello Story 這個 UILabel 傳到 Text Field 上,於是在 HelloController.h 要新增 IBOutlet UILabel * helloLabel。然後 prepareForSegue:sender: 改成如下。
在 Line 63 我們看到了 helloLabel.text 傳到 SecondController 實體的 Text Field 。執行之後就是如下。

恭喜大家。到此還沒介紹如何用到 Done 這個按鈕,還有我們接下來要反過來從 SecondController 實體傳資料給  HelloController 的實體。請期待下一篇。

3 則留言:

  1. 請問
    @Synthesize (property)
    (property)後面要打什麼呢??
    後面如果不打的話,會有錯誤!!!

    回覆刪除
    回覆
    1. @synthesize 後直接接上 property 名稱,就這樣而己。

      @property (strong) NSString * name; 和 @synthesize name;
      是成對出現,其上 name 就是 property 名稱。
      Xcode 4.4 有 LLVM 4.0 之後就不用寫 @synthesize 了。

      刪除
    2. 作者已經移除這則留言。

      刪除