iOS storyBoard全解析
阿新 • • 發佈:2019-02-09
(Storyboard)是一個能夠節省你很多設計手機App介面時間的新特性,下面,為了簡明的說明Storyboard的效果,我貼上本教程所完成的Storyboard的截圖:
現在,你就可以清楚的看到這個應用究竟是幹些什麼的,也可以清楚的看到其中的各種關係,這就是Storyboard的強大之處了。如果你要製作一個頁面很多很複雜的App,Storyboard可以幫助你解決寫很多重複的跳轉方法的麻煩,節省很多時間,以便你能夠完全的專注於核心功能的實現上。
開始
首先啟動Xcode,新建一個工程,我們在這裡使用Single View App Template,這個模板會提供一個類和一個Storyboard,免去我們自己建立的麻煩。
建立完成之後,Xcode的介面大概是這樣的:
這個新的工程由兩個類:AppDelegate和ViewController以及一個Storyboard組成(如果你選擇了兩個裝置會有兩個Storyboard),注意這個專案沒有xib檔案,讓我們首先看看Storyboard是什麼樣的,雙擊Storyboard開啟他:
Storyboard的樣子和工作方式都和Interface Builder(以下簡稱為IB)像極了,你可以從左下方的控制元件庫中拖動控制元件到你的View之中並且組織他們的排放順序,唯一不同的地方就是,Storyboard不止是包含一個檢視控制元件,而是所有的檢視控制元件以及他們之間的關係。
Storyboard對一個檢視的官方術語是一個場景,但是一個場景其實就是一個ViewController,在iPhone中一次只能夠展示一個場景,而在iPad中一次可以展示多個場景,比如Mail應用程式。
通過嘗試新增一些控制元件,你可以感受一下Storyboard的工作方式。
這個是資料顯示器,顯示所有場景及其控制元件的結構。
在IB中,這個位置顯示的是你的NIB檔案中的檔案,而在Storyboard中這裡顯示的是ViewController,目前這裡只有一個ViewController,我們接下來可能會增加一些。
這是一個文件管理器的縮小版,叫做dock。
Dock展示場景中第一級的控制元件,每個場景至少有一個ViewController和一個FirstReponder,但是也可以有其他的控制元件,Dock還用來簡單的連線控制元件,如果你需要向ViewController傳遞一個關係時,只需要將其按住Ctrl鍵拖到ViewController上就可以了。
Note:你大概不會太長使用FirstResponder,因為它只是一個代理控制元件,代表著當前你所使用的控制元件。
現在執行這個應用,他會向我們設計的介面一樣。
如果你以前製作過NIB型的應用的話,你也許回去尋找MainWindow.xib ,這個檔案包括所有的ViewController,Appdelegate等等,但是在Storyboard中這個特性已經被廢止了。
那麼,沒有這個檔案,應用從那裡起始呢?
讓我們開啟AppDelegate檔案,看看那上面是怎麼說的:
如果要使用Storyboard特性,那麼AppDelegate必須繼承自UIResponder類, 之前則是繼承自NSObject類的,而且必須有一個不是UIOutlet類的Window屬性宣告才可以。
如果你再去看AppDelegate的執行檔案,裡面大概什麼都沒有,甚至連 application:didFinishLaunchingWithOptions: 也只是返回了一個 YES,而之前,這裡則需宣告一個ViewController並且將他設定成起始頁面,但是現在這些都沒有了。
祕密就在info.plist檔案中, 開啟Ratings-Info.plist (在 Supporting Files group裡) 你就會看到這些:
在NIB為UI的應用裡,info.plist檔案中有一個鍵兼做NSMainNibFile,或者叫做Main nib file base name,他用來指示UIApplication載入MainWindow.xib,並且將他與應用連結起來,而現在這個鍵值消失了。
而Storyboard應用則利用 UIMainStoryboardFile,或者 “Main storyboard file base name” 鍵值來表示當App初始化時的Storyboard名稱,當程式執行時,UIApplication會使用MainStoryboard.sotryboard作為第一載入項,並且將他的UIWindow展示在螢幕上,不需要任何程式設計工作。
在專案總結面板上,你也可以看到並且編輯這些資訊:
如果你還想設定nib檔案的話,另外有地方去設定的。
為了完成這個實驗性的小程式,我們開啟main.m,加入
之前是UIApplicationMain()的函式現在是空的, 變成了 NSStringFromClass([AppDelegate class]).
與之前使用MainWindow.xib的一個最大的不同是:現在app delegate已經不是Storyboard的一部分了,這是因為app delegate不再從nib檔案中,而侍從Storyboard中載入了,我們必須告訴 UIApplicationMain 我們的app delegate類的名字是什麼,否則他將無法找到。
製作一個Tab型別的應用
本教程中的Rating App擁有兩個Tab,在Storyboard中,很輕鬆就能夠做出一個Tab檢視。
回到MainStoryboard.storyboard中,直接從左邊的Library拖進來一個TabViewController就可以了。
新的Tab Bar Controller附帶了兩個View controller,分別作為Tab的檢視使用,UITabBarController被稱為包含檢視,因為他包含這其他一些View,其他常見的包含檢視還有那vi嘎提鷗鳥 Controller和SplitView Controller。
在iOS 5中,你還可以自己寫一個自定義的Controller,這在以前是做不到的。
包含關係在Storyboard中用一下這種箭頭表示。
拉一個Label控制元件到第一個子試圖中,命名為“First Tab”,再在第二個子檢視中新增一個Label,命名為“Second Tab”。
注意:當螢幕的縮放大於100%時,你無法在單個場景中新增控制元件。
選中Tab Bar Controller,進入屬性檢查器,選中“作為起始場景”,如下圖:
現在那個沒有頭的虛虛的小箭頭指向了Tab Bar Controller,說明他是起始場景。
這意味著,當你啟動這個應用的時候,UIApplication將會將這個場景作為應用的主螢幕。
Storyboard一定要有一個場景是起始場景才行。
現在執行試試吧
code專門為創造這種Tab Bar的應用準備了一個模板,我們也可以使用他,但是自己有能力不用模板自己做一個Tab Bar也是不錯的事。
如果你添加了多於五個子檢視到一個TabBarcontroller的話,並不會創造五個Tab,第四個tab會自動變成More標籤,不錯吧
製作一個表格檢視
目前連線到Tab bar Controller的檢視都是普通的View Controller,現在,我要用一個TableViewController來代替其中的一個ViewController。
單擊第一個檢視並刪除,從Library中拖出一個TableViewController。
在選中這個TableViewController的前提下,從Library中拖出一個NavController,將會直接附著在上面。
當然也可以調換順序,我完全沒意見。
由於NavController和TabBarController一樣也是一個包含控制器檢視,所以他也必須包含另一個檢視,你可以看到同樣的箭頭連線者這兩個View。
請注意所有巢狀在NavController下的View都會有一個Navigation Bar,你無法移除它,因為他是一個虛擬的Bar。
如果你檢視屬性檢測器,你就會發現所有bar的屬性都在一起:
“Inferred”是Storyboard中的預設設定,他意味著繼承的關係,但是你也可以改變他。但是請注意這些設定都是為了讓你更好的進行設計和這樣設定的,隨意修改預設設定會帶來不可遇見的後果,施主自重。
現在讓我們把這個新的場景連線到Tab Bar Controller中,按住Ctrl拖動,或者右鍵。
當你放手的時候,一個提示框會出現。
當然是選第一個了,Relationship – viewControllers ,這將自動建立兩個場景之間的關係。
直接拖動就可以改變Tab Item的順序,同時也會改變顯示Tab的順序,放在最左邊的Tab會第一個顯示。
現在執行試試看吧
在我們在這個應用中加入任何實質性的功能之前,我們先來清理一下Storyboard,你不需要改變TabBarController中的任何內容而只需要改變他的子檢視就可以了。
每當你連線一個新的檢視到TabBarController中的時候,他就會自動增加一個Tab Item,你可以使用他的子檢視來修改該Item的圖片和名稱。
在NavController中選中Tab Item並且在屬性編輯其中將其修改為Player。
將第二個Tab Item命名為“Gesture”
我們接下來把自定義的圖片加入到這些item中, 原始碼 中包含一個名為“Image”的資料夾,在那裡你可以找到我們用到的資源。
接下來,將NavController的title改為Player,也可以使用程式碼··
執行看一看,難以置信吧,你到現在也沒寫一條程式碼。
原型表格單元
你也許已經注意到了,自從我們加入了Table View Controller之後,Xcode便會現實下面這樣一條警告。
這條警告是:“Unsupported Configuration: Prototype table cells must have reuse identifiers”意思是,原型表格單元必須有一個身份證(意譯啦)
原型單元格是另一個Storyboard的好特性之一。在之前,如果你想要自定義一個Table Cell,那麼你就不得不用程式碼來實現,要麼就要單獨建立一個Nib檔案來表示單元格內容,現在你也可以這樣做,不過原型單元格可以幫你把這一過程大大的簡化,你現在可以直接在Storyboard設計器中完成這一過程。
Table View現在預設的會帶有一個空白的原型單元格,選中他,在屬性控制器中將他的Style改為subtitle,這樣的話,每一格就會有兩行字。
將附件設定為Disclosure Indicator並且將這個原型單元格的Reuse Identifier 設定喂“PlayerCell”,這將會解決Xcode所警告的問題。
試著執行一個,發現什麼都沒變,這並不奇怪,因為我們還沒有給這個表格設定一個數據來源(DataSource),用以顯示。
新建一個檔案,使用UIViewContoller模板,命名為 PlayersViewController ,設定喂UITableViewController的子類,不要勾選建立XIB檔案。
回到Storyboard編輯器,選擇Table View Controller,在身份控制器中,把他的類設定為PlayerViewController,這對於把Storyboard中的場景和你自定義的子類掛鉤是十分重要的。要是不這麼做,你的子類根本沒用。
現在起,當你執行這個應用時,table view controller其實是PlayersViewContoller的一個例項。
在 PlayersViewController.h 中宣告一個MutableArray(可變陣列)
這個陣列將會包含我們的應用的主要資料模型。我們現在加一些東西到這個陣列之中,新建一個使用Obj-c模板的檔案,命名為player,設定喂NSObject的子類,這將會作為陣列的資料容器。
編寫Player.h如下:
編寫Player.m如下:
這裡沒有什麼複雜的,Player類只是一個容器罷了,包含三個內容:選手的名字、專案和他的評級。
接下來我們在App Delegate中宣告陣列和一些Player物件,並把他們分配給PlayerViewController的players屬性。
在AppDelegate.m中,分別引入(import)Player和PlayerViewController這兩個類,之後新增一個名叫players的可變陣列。
修改didFinishLaunchingWithOptions方法如下:
這將會創造一些Player物件並把他們加到陣列中去。之後在加入:
咦,這是什麼?目前的情況是:我們希望能夠將players陣列連線到PlayersViewController的players屬性之中以便讓這個VC能夠用做資料來源。但是app delegate根本不瞭解PlayerViewController究竟是什麼,他將需要在storyboard中尋找它。
這是一個我不是很喜歡storyboard特性,在IB中,你在MainWindow.xib中總是會有一個指向App delegate的選項,在那裡你可以在頂級的ViewController中向Appdelegate設定輸出口,但是在Storyboard中目前這還不可能,目前只能通過程式碼來做這樣的事情。
我們知道storyboard的起始場景是Tab Bar Controller,所以我們可以直接到這個場景的第一個子場景來設定資料來源。
PlayersViewController 在一個NavController的框架之中,所以我們先看一看UINavigationController類:
然後詢問它的根試圖控制器,哪一個是我們要找的PlayersViewController:
但是,UIViewController根本就沒有一個rootViewController屬性,所以我們不能把陣列加入進去,他又一個topViewController但是指向最上層的檢視,與我們這裡的意圖沒有關係。
現在我們有了一個裝在了players物體合集的陣列,我們繼續為PlayersViewController設定資料來源。
開啟PlayersViewController.m,加入以下資料來源方法:
真正起作用的程式碼在cellForRowAtIndexPath方法裡,預設的模板是如下這樣的
現在,你就可以清楚的看到這個應用究竟是幹些什麼的,也可以清楚的看到其中的各種關係,這就是Storyboard的強大之處了。如果你要製作一個頁面很多很複雜的App,Storyboard可以幫助你解決寫很多重複的跳轉方法的麻煩,節省很多時間,以便你能夠完全的專注於核心功能的實現上。
開始
首先啟動Xcode,新建一個工程,我們在這裡使用Single View App Template,這個模板會提供一個類和一個Storyboard,免去我們自己建立的麻煩。
建立完成之後,Xcode的介面大概是這樣的:
這個新的工程由兩個類:AppDelegate和ViewController以及一個Storyboard組成(如果你選擇了兩個裝置會有兩個Storyboard),注意這個專案沒有xib檔案,讓我們首先看看Storyboard是什麼樣的,雙擊Storyboard開啟他:
Storyboard的樣子和工作方式都和Interface Builder(以下簡稱為IB)像極了,你可以從左下方的控制元件庫中拖動控制元件到你的View之中並且組織他們的排放順序,唯一不同的地方就是,Storyboard不止是包含一個檢視控制元件,而是所有的檢視控制元件以及他們之間的關係。
Storyboard對一個檢視的官方術語是一個場景,但是一個場景其實就是一個ViewController,在iPhone中一次只能夠展示一個場景,而在iPad中一次可以展示多個場景,比如Mail應用程式。
通過嘗試新增一些控制元件,你可以感受一下Storyboard的工作方式。
這個是資料顯示器,顯示所有場景及其控制元件的結構。
在IB中,這個位置顯示的是你的NIB檔案中的檔案,而在Storyboard中這裡顯示的是ViewController,目前這裡只有一個ViewController,我們接下來可能會增加一些。
這是一個文件管理器的縮小版,叫做dock。
Dock展示場景中第一級的控制元件,每個場景至少有一個ViewController和一個FirstReponder,但是也可以有其他的控制元件,Dock還用來簡單的連線控制元件,如果你需要向ViewController傳遞一個關係時,只需要將其按住Ctrl鍵拖到ViewController上就可以了。
Note:你大概不會太長使用FirstResponder,因為它只是一個代理控制元件,代表著當前你所使用的控制元件。
現在執行這個應用,他會向我們設計的介面一樣。
如果你以前製作過NIB型的應用的話,你也許回去尋找MainWindow.xib ,這個檔案包括所有的ViewController,Appdelegate等等,但是在Storyboard中這個特性已經被廢止了。
那麼,沒有這個檔案,應用從那裡起始呢?
讓我們開啟AppDelegate檔案,看看那上面是怎麼說的:
- #import <UIKit/UIKit.h>
- @interface AppDelegate : UIResponder <UIApplicationDelegate>
- @property (strong, nonatomic) UIWindow *window;
- @end
如果要使用Storyboard特性,那麼AppDelegate必須繼承自UIResponder類, 之前則是繼承自NSObject類的,而且必須有一個不是UIOutlet類的Window屬性宣告才可以。
如果你再去看AppDelegate的執行檔案,裡面大概什麼都沒有,甚至連 application:didFinishLaunchingWithOptions: 也只是返回了一個 YES,而之前,這裡則需宣告一個ViewController並且將他設定成起始頁面,但是現在這些都沒有了。
祕密就在info.plist檔案中, 開啟Ratings-Info.plist (在 Supporting Files group裡) 你就會看到這些:
在NIB為UI的應用裡,info.plist檔案中有一個鍵兼做NSMainNibFile,或者叫做Main nib file base name,他用來指示UIApplication載入MainWindow.xib,並且將他與應用連結起來,而現在這個鍵值消失了。
而Storyboard應用則利用 UIMainStoryboardFile,或者 “Main storyboard file base name” 鍵值來表示當App初始化時的Storyboard名稱,當程式執行時,UIApplication會使用MainStoryboard.sotryboard作為第一載入項,並且將他的UIWindow展示在螢幕上,不需要任何程式設計工作。
在專案總結面板上,你也可以看到並且編輯這些資訊:
如果你還想設定nib檔案的話,另外有地方去設定的。
為了完成這個實驗性的小程式,我們開啟main.m,加入
- #import <UIKit/UIKit.h>
- #import "AppDelegate.h"
- int main(int argc, char *argv[])
- {
- @autoreleasepool {
- return UIApplicationMain(argc, argv, nil,
- NSStringFromClass([AppDelegate class]));
- }
- }
之前是UIApplicationMain()的函式現在是空的, 變成了 NSStringFromClass([AppDelegate class]).
與之前使用MainWindow.xib的一個最大的不同是:現在app delegate已經不是Storyboard的一部分了,這是因為app delegate不再從nib檔案中,而侍從Storyboard中載入了,我們必須告訴 UIApplicationMain 我們的app delegate類的名字是什麼,否則他將無法找到。
製作一個Tab型別的應用
本教程中的Rating App擁有兩個Tab,在Storyboard中,很輕鬆就能夠做出一個Tab檢視。
回到MainStoryboard.storyboard中,直接從左邊的Library拖進來一個TabViewController就可以了。
新的Tab Bar Controller附帶了兩個View controller,分別作為Tab的檢視使用,UITabBarController被稱為包含檢視,因為他包含這其他一些View,其他常見的包含檢視還有那vi嘎提鷗鳥 Controller和SplitView Controller。
在iOS 5中,你還可以自己寫一個自定義的Controller,這在以前是做不到的。
包含關係在Storyboard中用一下這種箭頭表示。
拉一個Label控制元件到第一個子試圖中,命名為“First Tab”,再在第二個子檢視中新增一個Label,命名為“Second Tab”。
注意:當螢幕的縮放大於100%時,你無法在單個場景中新增控制元件。
選中Tab Bar Controller,進入屬性檢查器,選中“作為起始場景”,如下圖:
現在那個沒有頭的虛虛的小箭頭指向了Tab Bar Controller,說明他是起始場景。
這意味著,當你啟動這個應用的時候,UIApplication將會將這個場景作為應用的主螢幕。
Storyboard一定要有一個場景是起始場景才行。
現在執行試試吧
code專門為創造這種Tab Bar的應用準備了一個模板,我們也可以使用他,但是自己有能力不用模板自己做一個Tab Bar也是不錯的事。
如果你添加了多於五個子檢視到一個TabBarcontroller的話,並不會創造五個Tab,第四個tab會自動變成More標籤,不錯吧
製作一個表格檢視
目前連線到Tab bar Controller的檢視都是普通的View Controller,現在,我要用一個TableViewController來代替其中的一個ViewController。
單擊第一個檢視並刪除,從Library中拖出一個TableViewController。
在選中這個TableViewController的前提下,從Library中拖出一個NavController,將會直接附著在上面。
當然也可以調換順序,我完全沒意見。
由於NavController和TabBarController一樣也是一個包含控制器檢視,所以他也必須包含另一個檢視,你可以看到同樣的箭頭連線者這兩個View。
請注意所有巢狀在NavController下的View都會有一個Navigation Bar,你無法移除它,因為他是一個虛擬的Bar。
如果你檢視屬性檢測器,你就會發現所有bar的屬性都在一起:
“Inferred”是Storyboard中的預設設定,他意味著繼承的關係,但是你也可以改變他。但是請注意這些設定都是為了讓你更好的進行設計和這樣設定的,隨意修改預設設定會帶來不可遇見的後果,施主自重。
現在讓我們把這個新的場景連線到Tab Bar Controller中,按住Ctrl拖動,或者右鍵。
當你放手的時候,一個提示框會出現。
當然是選第一個了,Relationship – viewControllers ,這將自動建立兩個場景之間的關係。
直接拖動就可以改變Tab Item的順序,同時也會改變顯示Tab的順序,放在最左邊的Tab會第一個顯示。
現在執行試試看吧
在我們在這個應用中加入任何實質性的功能之前,我們先來清理一下Storyboard,你不需要改變TabBarController中的任何內容而只需要改變他的子檢視就可以了。
每當你連線一個新的檢視到TabBarController中的時候,他就會自動增加一個Tab Item,你可以使用他的子檢視來修改該Item的圖片和名稱。
在NavController中選中Tab Item並且在屬性編輯其中將其修改為Player。
將第二個Tab Item命名為“Gesture”
我們接下來把自定義的圖片加入到這些item中, 原始碼 中包含一個名為“Image”的資料夾,在那裡你可以找到我們用到的資源。
接下來,將NavController的title改為Player,也可以使用程式碼··
執行看一看,難以置信吧,你到現在也沒寫一條程式碼。
原型表格單元
你也許已經注意到了,自從我們加入了Table View Controller之後,Xcode便會現實下面這樣一條警告。
這條警告是:“Unsupported Configuration: Prototype table cells must have reuse identifiers”意思是,原型表格單元必須有一個身份證(意譯啦)
原型單元格是另一個Storyboard的好特性之一。在之前,如果你想要自定義一個Table Cell,那麼你就不得不用程式碼來實現,要麼就要單獨建立一個Nib檔案來表示單元格內容,現在你也可以這樣做,不過原型單元格可以幫你把這一過程大大的簡化,你現在可以直接在Storyboard設計器中完成這一過程。
Table View現在預設的會帶有一個空白的原型單元格,選中他,在屬性控制器中將他的Style改為subtitle,這樣的話,每一格就會有兩行字。
將附件設定為Disclosure Indicator並且將這個原型單元格的Reuse Identifier 設定喂“PlayerCell”,這將會解決Xcode所警告的問題。
試著執行一個,發現什麼都沒變,這並不奇怪,因為我們還沒有給這個表格設定一個數據來源(DataSource),用以顯示。
新建一個檔案,使用UIViewContoller模板,命名為 PlayersViewController ,設定喂UITableViewController的子類,不要勾選建立XIB檔案。
回到Storyboard編輯器,選擇Table View Controller,在身份控制器中,把他的類設定為PlayerViewController,這對於把Storyboard中的場景和你自定義的子類掛鉤是十分重要的。要是不這麼做,你的子類根本沒用。
現在起,當你執行這個應用時,table view controller其實是PlayersViewContoller的一個例項。
在 PlayersViewController.h 中宣告一個MutableArray(可變陣列)
- #import <UIKit/UIKit.h>
- @interface PlayersViewController : UITableViewController
- @property (nonatomic, strong) NSMutableArray *players;
- @end
這個陣列將會包含我們的應用的主要資料模型。我們現在加一些東西到這個陣列之中,新建一個使用Obj-c模板的檔案,命名為player,設定喂NSObject的子類,這將會作為陣列的資料容器。
編寫Player.h如下:
- @interface Player : NSObject
- @property (nonatomic, copy) NSString *name;
- @property (nonatomic, copy) NSString *game;
- @property (nonatomic, assign) int rating;
- @end
編寫Player.m如下:
- #import "Player.h"
- @implementation Player
- @synthesize name;
- @synthesize game;
- @synthesize rating;
- @end
這裡沒有什麼複雜的,Player類只是一個容器罷了,包含三個內容:選手的名字、專案和他的評級。
接下來我們在App Delegate中宣告陣列和一些Player物件,並把他們分配給PlayerViewController的players屬性。
在AppDelegate.m中,分別引入(import)Player和PlayerViewController這兩個類,之後新增一個名叫players的可變陣列。
- #import "AppDelegate.h"
- #import "Player.h"
- #import "PlayersViewController.h"
- @implementation AppDelegate {
- NSMutableArray *players;
- }
- // Rest of file...
修改didFinishLaunchingWithOptions方法如下:
- - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
- {
- players = [NSMutableArray arrayWithCapacity:20];
- Player *player = [[Player alloc] init];
- player.name = @"Bill Evans";
- player.game = @"Tic-Tac-Toe";
- player.rating = 4;
- [players addObject:player];
- player = [[Player alloc] init];
- player.name = @"Oscar Peterson";
- player.game = @"Spin the Bottle";
- player.rating = 5;
- [players addObject:player];
- player = [[Player alloc] init];
- player.name = @"Dave Brubeck";
- player.game = @"Texas Hold’em Poker";
- player.rating = 2;
- [players addObject:player];
- UITabBarController *tabBarController =
- (UITabBarController *)self.window.rootViewController;
- UINavigationController *navigationController =
- [[tabBarController viewControllers] objectAtIndex:0];
- PlayersViewController *playersViewController =
- [[navigationController viewControllers] objectAtIndex:0];
- playersViewController.players = players;
- return YES;
- }
這將會創造一些Player物件並把他們加到陣列中去。之後在加入:
- UITabBarController *tabBarController = (UITabBarController *)
- self.window.rootViewController;
- UINavigationController *navigationController =
- [[tabBarController viewControllers] objectAtIndex:0];
- PlayersViewController *playersViewController =
- [[navigationController viewControllers] objectAtIndex:0];
- playersViewController.players = players;
咦,這是什麼?目前的情況是:我們希望能夠將players陣列連線到PlayersViewController的players屬性之中以便讓這個VC能夠用做資料來源。但是app delegate根本不瞭解PlayerViewController究竟是什麼,他將需要在storyboard中尋找它。
這是一個我不是很喜歡storyboard特性,在IB中,你在MainWindow.xib中總是會有一個指向App delegate的選項,在那裡你可以在頂級的ViewController中向Appdelegate設定輸出口,但是在Storyboard中目前這還不可能,目前只能通過程式碼來做這樣的事情。
- UITabBarController *tabBarController = (UITabBarController *)
- self.window.rootViewController;
我們知道storyboard的起始場景是Tab Bar Controller,所以我們可以直接到這個場景的第一個子場景來設定資料來源。
PlayersViewController 在一個NavController的框架之中,所以我們先看一看UINavigationController類:
- UINavigationController *navigationController = [[tabBarController
- viewControllers] objectAtIndex:0];
然後詢問它的根試圖控制器,哪一個是我們要找的PlayersViewController:
- PlayersViewController *playersViewController =
- [[navigationController viewControllers] objectAtIndex:0];
但是,UIViewController根本就沒有一個rootViewController屬性,所以我們不能把陣列加入進去,他又一個topViewController但是指向最上層的檢視,與我們這裡的意圖沒有關係。
現在我們有了一個裝在了players物體合集的陣列,我們繼續為PlayersViewController設定資料來源。
開啟PlayersViewController.m,加入以下資料來源方法:
- - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
- {
- return 1;
- }
- - (NSInteger)tableView:(UITableView *)tableView
- numberOfRowsInSection:(NSInteger)section
- {
- return [self.players count];
- }
真正起作用的程式碼在cellForRowAtIndexPath方法裡,預設的模板是如下這樣的