日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

storyboard 使用

發(fā)布時(shí)間:2023/12/8 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 storyboard 使用 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
Storyboard是一項(xiàng)令人興奮的功能,在iOS5中首次推出,在開(kāi)發(fā)app的界面時(shí)可以極大地節(jié)省時(shí)間。 如下圖所示,這就是一個(gè)完整的應(yīng)用的storyboard,接下來(lái)我們要學(xué)習(xí)如何通過(guò)這種方式創(chuàng)建應(yīng)用。 現(xiàn)在你可能還不是很精確地知道我們的應(yīng)用可以做什么,但是通過(guò)上圖,我們可以很清晰的明白這些視圖之間的關(guān)系。這就是使用storyboard的強(qiáng)大之處。 當(dāng)你的應(yīng)用有許多不同頁(yè)面的時(shí)候,通過(guò)使用storyboard,可以大大減少頁(yè)面之間跳轉(zhuǎn)的代碼。過(guò)去我們?yōu)槊總€(gè)視圖控制器創(chuàng)建一個(gè)nib文件,現(xiàn)在,只需要使用一個(gè)storyboard,它包含了你應(yīng)用中所有的視圖控制器以及它們之間的關(guān)系。 相比傳統(tǒng)的nib文件,storyboard有很多優(yōu)點(diǎn): 1.使用storyboard,可以更好地理解應(yīng)用中所有視圖在概念上的概覽以及它們之間的關(guān)系。掌控所有的視圖變得很容易,因?yàn)樗械脑O(shè)計(jì)都是在一個(gè)文件中,而不是在很多單獨(dú)的nib文件中。 2.storyboard描述了視圖之間的動(dòng)畫(huà),這些動(dòng)畫(huà)叫做"segues"你可以很容易的通過(guò)從一個(gè)視圖控制器(點(diǎn)ctrl-dragging)拖拽到另一個(gè)來(lái)實(shí)現(xiàn),感謝"segues"讓我們不需要寫(xiě)代碼去控制頁(yè)面跳轉(zhuǎn)了。 3.storyboard通過(guò)新的cell原型,以及靜態(tài)cell的特性,讓表格控制器實(shí)現(xiàn)起來(lái)更容易了。你近乎可以完全的通過(guò)storyboard來(lái)設(shè)計(jì)你的表格控制器,這也大大的減少了你不得不寫(xiě)的代碼量。. 并不是所有的都是那么完美,當(dāng)然使用storyboard也是有一些限制的,storyboard的Interface builder 遠(yuǎn)沒(méi)有舊版nib編輯器那么強(qiáng)大,并且有一些東西只能在nib中做而不能在storyboard編輯器中做。還有,你需要一個(gè)大號(hào)的顯示器,尤其是在開(kāi)發(fā)iPad應(yīng)用的時(shí)候。 如果你是那種不喜歡用Interface builder 畫(huà)界面而是用代碼直接寫(xiě)界面的人,很遺憾,storyboard并不適合你。就個(gè)人而言,我比較傾向于寫(xiě)的代碼越少越好,特別是控制UI的那種,所以storyboard簡(jiǎn)直就是為我準(zhǔn)備的一把利器。 當(dāng)然了,如果你想繼續(xù)使用nib,那么繼續(xù)用好了,你需要知道的是你可以通過(guò)storyboard來(lái)綁定各視圖控制器,對(duì)于使用storyboard,還是舊版的nib,不是一個(gè)非做選擇不可的事,隨你好了。 在這個(gè)例子中,我們將會(huì)學(xué)到--通過(guò)storyboard我們可以做什么,我們將會(huì)創(chuàng)建一個(gè)簡(jiǎn)單的應(yīng)用,功能大致是有一個(gè)現(xiàn)實(shí)玩家,游戲,以及玩家技能評(píng)分的這么一個(gè)列表。在學(xué)習(xí)過(guò)程中,你幾乎可以學(xué)到大多數(shù)通過(guò)故事板可以做到的事。 storyboard教程 : iOS 7 版 打開(kāi)Xcode創(chuàng)建一個(gè)新項(xiàng)目,這里我們用 Single View Application 模板: 按照下面的方式填寫(xiě)模板中的選項(xiàng): 1.Product Name: Ratings 2.Organization Name: 隨便寫(xiě)點(diǎn)什么都行 3.Company Identifier:域名反過(guò)來(lái)寫(xiě),例如com.xx.xx 4.Class Prefix: 空著就行 5.Devices: iPhone 用舊版Xcode的時(shí)候你需要特別指定下這個(gè)新項(xiàng)目是用storyboard的,但XCode5之后,不再有這個(gè)選項(xiàng)了,默認(rèn)就是用storyboard創(chuàng)建的項(xiàng)目。 在Xcode創(chuàng)建完項(xiàng)目之后,Xcode的主界面上應(yīng)該如下圖所示: 這個(gè)新項(xiàng)目包含2個(gè)類(lèi):AppDelegate?和?ViewController, 以及我們這個(gè)例子中的明星:?Main.storyboard?文件. 請(qǐng)注意,這個(gè)項(xiàng)目中并沒(méi)有xib文件。 這是一個(gè)只支持豎屏的應(yīng)用,所以在繼續(xù)之前, 鉤掉?Deployment Info, Device Orientation下面的 Landscape Left和Landscape Right 選項(xiàng)。 接下來(lái)讓我們看一下storyboard,點(diǎn)擊列表中的 Main.storyboard 在interface builder中打開(kāi)它。 在Interface builder中編輯storyboard就跟編輯nib文件差不多,你可以從Object Library中拖拽新的元素到視圖控制器中,并且可以編輯它的布局。區(qū)別在于storyboard不僅僅有一個(gè)視圖控制器,它把你應(yīng)用中的所有視圖控制器全都包含了。 按標(biāo)準(zhǔn)的storyboard的說(shuō)法,一個(gè)視圖控制器就是一個(gè)"場(chǎng)景"。你可以交替的使用這個(gè)模式,"場(chǎng)景"是呈現(xiàn)在storyboard中的視圖控制器,以往,你可能為每一個(gè)"場(chǎng)景"/視圖控制器創(chuàng)建一個(gè)nib文件。現(xiàn)在你只需要把他們都集中在一個(gè)storyboard里。在iPhone中,一次只能看到一個(gè)場(chǎng)景,而iPad應(yīng)用中,一次可能會(huì)看到多個(gè)。例如"master/detail "或者 "popover" 注意:?Xcode 5默認(rèn)storyboard以及nib中的 Auto Layout屬性是打開(kāi)的。 Auto Layout 是一個(gè)新的很帥氣的可以自動(dòng)調(diào)整控件大小的這么一個(gè)技術(shù),在應(yīng)用適配iPad以及iPhone5的時(shí)候尤其有用,可惜它只能在 iOS 6 以上運(yùn)行。當(dāng)然了,它也需要一定的學(xué)習(xí)曲線,這個(gè)例子中我們不會(huì)詳細(xì)的說(shuō)這點(diǎn)。如果你有興趣了解 Auto Layout,請(qǐng)參閱我們的書(shū)籍《 iOS 6 by Tutorials andiOS 7 by Tutorials》. 在storyboard中的File inspector ?禁用Auto Layout選項(xiàng),如下圖: 拖拽一些控件到空的視圖控制器上,感受一些storyboard編輯器是如何工作的。 在storyboard編輯頁(yè)面中找到下面這個(gè)標(biāo)上紅色左箭頭的按鈕 點(diǎn)擊它打開(kāi)左側(cè)的 Document Outline 視圖 當(dāng)編輯nib的時(shí)候,列表中顯示的是這個(gè)nib中所有的控件,但對(duì)于storyboard,它會(huì)顯示你的應(yīng)用中的所有視圖控制器的內(nèi)容。上圖只有一個(gè)視圖控制器,在接下來(lái)的例子中,我們會(huì)增加其他的。 在scene下面有微型版的Document Outline,叫做Dock, 如下圖: 什么是 Dock ? 它顯示了當(dāng)前視圖的最上層對(duì)象,每個(gè)視圖都至少有一個(gè)View Controller 對(duì)象,一個(gè)First Responder 對(duì)象,一個(gè)Exit 項(xiàng)目。當(dāng)然了,它也可能會(huì)有其他的最上層對(duì)象。使用Dock 去連接outlets 和 actions變的非常容易,當(dāng)你想把某個(gè)對(duì)象連接到視圖控制器中時(shí),只需簡(jiǎn)單地把它的圖標(biāo)拖拽到Dock上。 注意: 你很可能沒(méi)怎么用過(guò)First Responder。這是指任何物體在任何給定時(shí)間具有第一響應(yīng)狀態(tài)的代理對(duì)象。它一直在你的nib中,你很可能從來(lái)沒(méi)有必要使用它。舉個(gè)例子,按鈕中有個(gè)Touch Up Inside事件,把它拖給First Responder的 cut: selector。如果在某一點(diǎn)的文本字段具有輸入焦點(diǎn),那么你可以按下該按鈕,使文字欄位,也就是現(xiàn)在的第一響應(yīng)者,切其文本到剪貼板。 運(yùn)行該app,它看起來(lái)應(yīng)該和你在編輯器中設(shè)計(jì)的一樣(此處使用了運(yùn)行iOS 7的4-inch Retina iPhone simulator): 如果你寫(xiě)過(guò)以nib為基礎(chǔ)的應(yīng)用,通常會(huì)有一個(gè)叫做MainWindow.xib的文件。這個(gè)文件有一個(gè)UIWindow對(duì)象指向App Delegate,以及其他視圖控制器。當(dāng)你想用storyboard做這些的時(shí)候,就不需要MainWindow.xib了。那么storyboard是如何加載到應(yīng)用中的呢? 讓我們看看應(yīng)用的 application delegate。 打開(kāi) AppDelegate.h,看起來(lái)應(yīng)該是這樣:
  • #import?<UIKit/UIKit.h>?
  • ??
  • @interface?AppDelegate?:?UIResponder?<UIApplicationDelegate>?
  • ??
  • @property?(strong,?nonatomic)?UIWindow?*window;?
  • ??
  • @end?
  • 使用storyboard,應(yīng)用代理必須繼承自UIResponder,并且有一個(gè) UIWindows 屬性。下面打開(kāi)AppDelegate.m,這里設(shè)么都沒(méi)有,所有的方法都是空的,甚至application:didFinishLaunchingWithOptions:??也僅僅是返回了一個(gè)YES。 秘密藏在Ratings-Info.plist?里,讓我們?cè)赟upporting Files group 里找到并打開(kāi)它,如下圖: storyboard使用UIMainStoryboardFile?或者"Main storyboard file base name" 來(lái)指定當(dāng)應(yīng)用啟動(dòng)的時(shí)候,哪一個(gè)storyboard是必須被加載的。當(dāng)設(shè)置生效,UIApplication會(huì)自動(dòng)加載叫這個(gè)被命名的storyboard文件,并把它第一個(gè)視圖控制器顯示到UIWindow中。這些都不必寫(xiě)代碼去實(shí)現(xiàn)。這些你還可以通過(guò)修改?Project Settings下面的Project Settings來(lái)實(shí)現(xiàn),如下圖: 出于完整性, 打開(kāi) main.m 如下圖:
  • #import?<UIKit/UIKit.h>?
  • ??
  • #import?"AppDelegate.h"?
  • ??
  • int?main(int?argc,?char?*argv[])?
  • {?
  • ????@autoreleasepool?{?
  • ????????return?UIApplicationMain(argc,?argv,?nil,?NSStringFromClass([AppDelegate?class]));?
  • ????}?
  • }?
  • app delegate 并不是storyboard的一部分,我們需要把它的名字指定給UIApplicationMain()?否則,應(yīng)用就會(huì)找不到它。 把它加到標(biāo)簽上? 這個(gè)Ratings 應(yīng)用是由標(biāo)簽控制的2個(gè)視圖 ,使用storyboard,創(chuàng)建標(biāo)簽很容易。 回到Main.storyboard, 把一個(gè)Tab Bar Controller 從Object Library 拖到面板中。你可能需要最大化你的XCode,因?yàn)門(mén)ab Bar Controller 默認(rèn)會(huì)帶 2個(gè)視圖控制器,你需要能完整的看到他們,通過(guò)右下角的小浮動(dòng)窗口,可以縮小這個(gè)面板。 一個(gè)新的Tab Bar Controller 默認(rèn)會(huì)帶2個(gè)視圖管理器,一個(gè)標(biāo)簽一個(gè)。UITabBarController也被叫做容器視圖控制器,因?yàn)橐话闼紩?huì)包含一個(gè)以上的視圖控制器。此外還有其他兩種容器控制器:Navigation Controller和the Split View Controller。 容器控制器通過(guò)箭頭管理它的視圖,如下圖 注意:?如果你想把Tab Bar Controller 的所有視圖一起移動(dòng),你需要點(diǎn)?-click選中這些視圖,然后再移動(dòng)他們(被選中的視圖會(huì)有一個(gè)藍(lán)色的下劃線)。 在第一個(gè)視圖控制器中拖入一個(gè)label并且設(shè)置它的text 為 "First Tab",同理,在第二個(gè)視圖管理器中加入"Second Tab" 這可以讓你看到標(biāo)簽切換后會(huì)發(fā)生什么情況。 注意:?在編輯器縮小的時(shí)候你不能向面板中拖入控件,你要先恢復(fù)到正常縮放水平,雙擊當(dāng)前面板就可以做到。 選中Tab Bar Controller 看下面板中的?Attributes inspector。選中那一欄指的是?Initial View Controller。如下圖: 在畫(huà)布上,先由一個(gè)箭頭指向Tab bar controller 這意味著啟動(dòng)app時(shí),?UIApplication?會(huì)把Tabbarcontroller 作為主控制器。storyboard同伴有一個(gè)獨(dú)立的視圖控制器,他是特定的" initial view controller", 它是storyboard的切入點(diǎn)。 提示:?改變 initial view controller ,你可以通過(guò)拖拽在視圖控制器之間的箭頭。 運(yùn)行應(yīng)用試試吧,現(xiàn)在應(yīng)用的效果是有一個(gè)tab bar 并且可以通過(guò)tab 去切換視圖。如下圖: Xcode 可以創(chuàng)建一個(gè)以tab為模板的項(xiàng)目(Tabbed Application template) ,你以前應(yīng)該用過(guò), 最好理解下它是如何工作的,如果非手動(dòng)創(chuàng)建,也不至于手足無(wú)措。 注意:?當(dāng)你想Tabbarcontroller 中加入超過(guò)5個(gè)視圖的時(shí)候,它會(huì)自動(dòng)的生產(chǎn)一個(gè) More的tab。 刪除模板自帶的那個(gè)視圖控制器,現(xiàn)在storyboard中只有一個(gè)tab bar 以及兩個(gè)tab各自對(duì)應(yīng)的一個(gè)視圖。 添加一個(gè)Table View Controller 兩個(gè)scene隸屬的Tab Bar Controller都是標(biāo)準(zhǔn)的 UIViewControllers,下面我們用UITableViewController 替換掉 第一個(gè)tab 中的scene。 點(diǎn)擊并選中第一個(gè)視圖控制器,然后刪除它,從Object Library中拖拽一個(gè)新的?Table View Controller?到先前被刪除的scene所處的位置。如下圖: 當(dāng)Table View Controller選中時(shí),在Xcode菜單欄選擇?Editor\Embed In\Navigation Controller?,現(xiàn)在另一個(gè)視圖控制器被加到畫(huà)板中了: 你還需要從Object Library中拖一個(gè)Navigation Controller,但這種嵌入在命令行中一樣簡(jiǎn)單。 因?yàn)镹avigation Controller 也是一個(gè)容器視圖控制器(跟Tab Bar Controller一樣), 它有一個(gè)關(guān)系箭頭指向Table View Controller,你還可以在 Document Outline看到這個(gè)關(guān)系: 注意:嵌入Table View Controller給了它一個(gè)navigation bar,Interface Builder 自動(dòng)加上它的,因?yàn)楫?dāng)前視圖會(huì)顯示在Navigation Controller的frame里。它并不是一個(gè)真的UINavigationBar ,只是一個(gè)模擬的。 打開(kāi)Table View Controller的?Attributes inspector, 你會(huì)看到上方有 Simulated Metrics 選項(xiàng),如下圖: "Inferred" 作為storyboards的默認(rèn)值,它意味著視圖將會(huì)顯示一個(gè)navigation bar,當(dāng)它處于Navigation Controller中時(shí),顯示一個(gè)tab bar 當(dāng)它處于Tab Bar Controller中時(shí)。你可以修改這些默認(rèn)設(shè)置,但是注意,這里只是方便你設(shè)計(jì)用的,"Simulated Metrics"并不會(huì)在運(yùn)行時(shí)出現(xiàn),他們是指一個(gè)虛擬的設(shè)計(jì),用來(lái)展示你的視圖最終會(huì)是什么樣子。 把這兩個(gè)視圖連接到Tab Bar Controller,按Ctrl-drag 從 the Tab Bar Controller 到 the Navigation Controller如下圖: 松手的時(shí)候, 出現(xiàn)一個(gè)彈出窗口如下圖: 選擇 Relationship Segue - view controllers,它為2個(gè)視圖創(chuàng)建了一個(gè)關(guān)系箭頭如下圖: Tab Bar Controller有2個(gè)關(guān)系, 給每個(gè)tab都有一個(gè)。Navigation Controller自己有一個(gè)關(guān)系指向Table View Controller。還有另一種類(lèi)型的箭頭"segue" 稍后我們會(huì)講到它。 創(chuàng)建完這個(gè)新的連接后,一個(gè)新的tab 添加到 Tab Bar Controller了, 簡(jiǎn)單的命名為 "Item"。對(duì)于這個(gè)應(yīng)用,你希望這個(gè)新視圖作為第一個(gè)tab,所以拖動(dòng)tabs,改變他們的順序如下圖: 運(yùn)行應(yīng)用,第一個(gè)tab顯示了一個(gè)包含在navagationcontroller 下面的 table view,如下圖: 在你為應(yīng)用添加具體的功能之前,讓我們先整理下storyboard,分別把第一個(gè)tab 第二個(gè)tab 命名為 ?"Players" 和"Gestures"。并不像你期望的那樣,你不能在Tab Bar Controller 上改動(dòng),只可以在tab 指向的那個(gè)視圖控制器上做。 一旦你把一個(gè)視圖控制器連上了Tab Bar Controller,它默認(rèn)會(huì)給一個(gè) Tab Bar Item 對(duì)象。用這個(gè)Tab Bar Item 去改變tab的名字跟圖片。 選中Navigation Controller里的Tab Bar Item ,在Attributes inspector中把title 設(shè)置為 Players,如下圖: 同理把第二個(gè)tab 設(shè)置為 Gestures. 一個(gè)設(shè)計(jì)良好的應(yīng)用需要在tab 上有圖標(biāo)。 這里例子代碼中 有個(gè)Images 的文件夾在 resource 文件夾下 把這個(gè)文件夾加入到項(xiàng)目中 ,選中Players Tab Bar的 Item的 Attributes inspector ,把 Players.png 填進(jìn)去. 同理處理 Gestures item the 圖片為 Gestures.png. 一個(gè)嵌入在Navigation Controller ?的視圖控制器有一個(gè) Navigation Item,它是用來(lái)配制navigation bar的。在Table View Controller 中選中Navigation Item (在Document Outline可以找到)在 Attributes inspector 中把title改成 ?Players. 此外, 你可以雙擊navigation bar 直接修改title. (注意: 你需要雙擊table view controller 中的simulated navigation bar,并不是Navigation Controller 中的真正的那個(gè)Navigation Bar 對(duì)象),如下圖 ? 運(yùn)行應(yīng)用,看看這令人驚嘆的tab bar吧,這一切,一行代碼都不用寫(xiě)喔~ Prototype cells Prototype cells 允許你在storyboard編輯器中直接為table view 設(shè)計(jì)自定義cell。 默認(rèn)Table View Controller 會(huì)帶一個(gè)空的cell. 點(diǎn)擊它,設(shè)置 Attributes inspector 中的 Style 為 Subtitle. 這會(huì)讓你的cell 包含2個(gè) labels.如果你以前為table view 做過(guò)自定義cell,你可能注意到,這就是UITableViewCellStyleSubtitle?風(fēng)格。通過(guò) prototype cells你可以像剛剛那樣直接選擇自帶的cell 風(fēng)格,或者純粹自己做一個(gè)設(shè)計(jì)。 設(shè)置 Accessory attribute 為?Disclosure Indicator?在 Identifier 中輸入 PlayerCell. 所有的 prototype cells 仍然是 UITableViewCell 類(lèi)型 所以它們需要一個(gè)reuse identifier,如下圖: 運(yùn)行應(yīng)用…什么都沒(méi)變?這并沒(méi)有什么值得奇怪的,你還需要為 這個(gè)tableview 指定一個(gè)data source,這樣它才會(huì)知道顯示什么。 添加一個(gè)新文件,選擇?Objective-C class?模板,命名為?PlayersViewController?,并且確保它是UITableViewController?的子類(lèi)。不要選中With XIB for user interface 選項(xiàng),因?yàn)槟阋呀?jīng)在storyboard中設(shè)計(jì)好它了,如下圖: 回到storyboard選擇Table View Controller (確保你只選擇了 tableviewcontroller 并沒(méi)有其他的view 包含在內(nèi))。在 Identity inspector中設(shè)置它的 Class 為 PlayersViewController. 這對(duì)于在storyboard中使用你自己定義的 視圖控制器的類(lèi)很重要,因?yàn)槿绻悴贿@么做,你的類(lèi)永遠(yuǎn)都不會(huì)被使用!如下圖: 到目前為止 當(dāng)你運(yùn)行應(yīng)用的時(shí)候,你的tableviewcontroller 是從storyboard中加載的你的PlayersViewController?的實(shí)例。 添加一個(gè)?mutable array property?到?PlayersViewController.h
  • #import?<UIKit/UIKit.h>?
  • ??
  • @interface?PlayersViewController?:?UITableViewController?
  • ??
  • @property?(nonatomic,?strong)?NSMutableArray?*players;?
  • ??
  • @end?
  • 該數(shù)組將會(huì)包含你的應(yīng)用中的主要數(shù)據(jù)模型,一個(gè)數(shù)組包含 Player 對(duì)象。使用Objective-C class模板在項(xiàng)目中添加一個(gè)新文件,命名為Player, 繼承自 NSObject. 把?Player.h?改成下圖的樣子:
  • @interface?Player?:?NSObject?
  • ??
  • @property?(nonatomic,?copy)?NSString?*name;?
  • @property?(nonatomic,?copy)?NSString?*game;?
  • @property?(nonatomic,?assign)?int?rating;?
  • ??
  • @end?
  • 這并沒(méi)有什么特別的. Player ?是一個(gè)簡(jiǎn)單的容器對(duì)象包含三個(gè)屬性:玩家名字,游戲名字,他游戲的評(píng)級(jí)(1-5星)。 在App Delegate 中你需要為這個(gè)數(shù)組創(chuàng)建一些測(cè)試的Player?對(duì)象,并且把它分配給PlayersViewController的 players 屬性。 在?AppDelegate.m中,在文件頂部為PlayerPlayersViewController添加#import ,并且添加一個(gè)實(shí)例變量?_players?,如下圖:
  • #import?"AppDelegate.h"?
  • #import?"Player.h"?
  • #import?"PlayersViewController.h"?
  • ??
  • @implementation?AppDelegate??
  • {?
  • ????NSMutableArray?*_players;?
  • }?
  • ??
  • //?Rest?of?file...?
  • 修改 application: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][0];?
  • ????PlayersViewController?*playersViewController?=?[navigationController?viewControllers][0];?
  • ????playersViewController.players?=?_players;?
  • ??
  • ????return?YES;?
  • }?
  • 我們創(chuàng)建了一些 Player 對(duì)象并且把它們加到了 _players 數(shù)組中,接下來(lái):
  • UITabBarController?*tabBarController?=?(UITabBarController?*)self.window.rootViewController;?
  • UINavigationController?*navigationController?=?[tabBarController?viewControllers][0];?
  • PlayersViewController?*playersViewController?=?[navigationController?viewControllers][0];?
  • playersViewController.players?=?_players;?
  • 嗯?! 我們想把?_players?array 分配給PlayersViewController?的?players?property,那樣它才能把這個(gè)數(shù)組作為它的data source,但是 app delegate并不知道?PlayersViewController是什么玩意,它會(huì)通過(guò)storyboard找到它。 注意:這是storyboard的一個(gè)限制。用nib的時(shí)候你需要在App Delegate 中指定MainWindow.xib 的引用,你可以通過(guò)連接頂層的視圖控制器到你的App Delegate中。在storyboard里,這是不可能的,你不能在app delegate中為你的頂層視圖控制器做引用,這很不幸,所以我們一般都手動(dòng)的寫(xiě),就像你現(xiàn)在做的這樣。 讓我們一步一步來(lái)
  • UITabBarController?*tabBarController?=?(UITabBarController?*)self.window.rootViewController;?
  • 你知道 storyboard最初的view controller 是一個(gè)Tab Bar Controller,所以你可以指定window的rootViewController 為 UITabBarController. 在第一個(gè)tab中,PlayersViewController位于navigation controller,所以你首先要查詢(xún)UINavigationController 對(duì)象,代碼如下:
  • UINavigationController?*navigationController?=?[tabBarController?viewControllers][0];?
  • 然后獲取它的root view controller, 這里是PlayersViewController:
  • PlayersViewController?*playersViewController?=?[navigationController?viewControllers][0];?
  • 為storyboard制作你想要的視圖控制器看來(lái)是需要花一些時(shí)間的,當(dāng)然了,如果你想換tab的順序,或者當(dāng)前應(yīng)用不是以tab bar controller 作為 rootviewcontroller了,你將不得不修改這個(gè)邏輯。 現(xiàn)在我們有了一個(gè)包含Player對(duì)象的數(shù)組了,我們可以為PlayersViewController創(chuàng)建datasource了。打開(kāi)PlayersViewController,在頂部添加import:
  • #import?"Player.h"?
  • 修改 table view data source 方法如下
  • -?(NSInteger)numberOfSectionsInTableView:(UITableView?*)tableView?
  • {?
  • ????return?1;?
  • }?
  • ??
  • -?(NSInteger)tableView:(UITableView?*)tableView?numberOfRowsInSection:(NSInteger)section?
  • {?
  • ????return?[self.players?count];?
  • }?
  • 真正的操作發(fā)生在cellForRowAtIndexPath 中,起初方法如下:
  • -?(UITableViewCell?*)tableView:(UITableView?*)tableView?cellForRowAtIndexPath:(NSIndexPath?*)indexPath?
  • {?
  • ????static?NSString?*CellIdentifier?=?@"Cell";?
  • ??
  • ????UITableViewCell?*cell?=?[tableView?dequeueReusableCellWithIdentifier:CellIdentifier];?
  • ????if?(cell?==?nil)?{?
  • ????????cell?=?[[UITableViewCell?alloc]?initWithStyle:UITableViewCellStyleDefault?
  • ??????????????????????????????????????reuseIdentifier:CellIdentifier];?
  • ????}?
  • ??
  • ????//?Configure?the?cell...?
  • ????return?cell;?
  • }?
  • 你需要問(wèn)你的table view 列出一個(gè)cell,如果它返回nil?則說(shuō)明當(dāng)前并無(wú)可重用的cell,所以你需要自己創(chuàng)建一個(gè)新的cell類(lèi)實(shí)例,毫無(wú)疑問(wèn)這需要你手寫(xiě)代碼了,用以下方法代替:
  • -?(UITableViewCell?*)tableView:(UITableView?*)tableView?cellForRowAtIndexPath:(NSIndexPath?*)indexPath?
  • {?
  • ????UITableViewCell?*cell?=?[tableView?dequeueReusableCellWithIdentifier:@"PlayerCell"];?
  • ??
  • ????Player?*player?=?(self.players)[indexPath.row];?
  • ????cell.textLabel.text?=?player.name;?
  • ????cell.detailTextLabel.text?=?player.game;?
  • ??
  • ????return?cell;?
  • }?
  • 這看起來(lái)很簡(jiǎn)單,你只需要像下面獲取cell
  • UITableViewCell?*cell?=?[tableView?dequeueReusableCellWithIdentifier:@"PlayerCell"];?
  • 如果當(dāng)前沒(méi)有一個(gè)可以重用的cell 它會(huì)自動(dòng)返回一個(gè)prototype cell 的copy 并且返給你。下面你就需要使用在storyboard編輯器中設(shè)置的re-use identifier,這里是"PlayerCell" 運(yùn)行應(yīng)用,table view如下圖所示: 僅僅需要一行代碼就可以實(shí)現(xiàn)這個(gè)新奇的prototype cells。 注意:這個(gè)應(yīng)用我們只用到了一種prototype的cell,如果你想用更多種類(lèi)的cell,只需要簡(jiǎn)單地把那些額外的prototype cell 加到storyboard上,你也可以復(fù)制當(dāng)前存在的cell 去做一個(gè)新的,或者增加當(dāng)前table view 的Prototype cell的屬性,但是要確保一點(diǎn),每個(gè)cell都需要有一個(gè)只屬于它自己的re-use identifier 設(shè)計(jì)你自己的Prototype Cells 很多app 都是使用 默認(rèn)的cell style的,但是對(duì)于這個(gè)應(yīng)用,cell 的右側(cè)有一個(gè)圖片用來(lái)顯示這個(gè)用戶(hù)的得分(從1星到5星),默認(rèn)的cell不帶這種具有image的style,所以這里我們需要自己設(shè)計(jì)一個(gè)。 回到Main.storyboard,選擇table view 中的prototype cell并把它的Style attribute 設(shè)置為Custom,默認(rèn)的labels 現(xiàn)在沒(méi)有了。 第一步把cell 稍微加高一點(diǎn),通過(guò)拖拽它的下邊,或者改變Size inspector中的Row Height值都可以。 把cell的高度設(shè)置為55 points。從Objects Library 拽2個(gè) Label 到cell 上, 把他們放在剛才那個(gè)label 所在的地方,隨便改改顏色 字圖或者寫(xiě)點(diǎn)什么都行。 拖一個(gè)Image View?到cell 上,并讓它居于cell的右側(cè),緊挨著disclosure indicator 設(shè)置它的Mode 為 Center (在Attributes inspector的view 下面),這樣無(wú)論你防止什么樣的圖片到這個(gè)Imageview 上它都不會(huì)被拉伸。 設(shè)置 labels 的寬度為190 points 這樣他們就不會(huì)擋住image view。 最終的效果如下圖所示: 因?yàn)檫@是一個(gè)自定義cell所以你再也不需要 UITableViewCell 中的textLabeldetailTextLabel?屬性來(lái)設(shè)置text。因?yàn)檫@些屬性指向的 labels 在這個(gè)cell中并不存在了。作為替代,你需要使用tags 來(lái)找到這些labels。 給Name label 的tag 設(shè)置為100,Game 的label 設(shè)置為101,Image View 的tag設(shè)置為102,通過(guò)Attributes inspector 可以找到。 下面打開(kāi)PlayersViewController.m?增加一個(gè)方法,imageForRating:. 如下:
  • -?(UIImage?*)imageForRating:(int)rating?
  • {?
  • ????switch?(rating)?{?
  • ????????case?1:?return?[UIImage?imageNamed:@"1StarSmall"];?
  • ????????case?2:?return?[UIImage?imageNamed:@"2StarsSmall"];?
  • ????????case?3:?return?[UIImage?imageNamed:@"3StarsSmall"];?
  • ????????case?4:?return?[UIImage?imageNamed:@"4StarsSmall"];?
  • ????????case?5:?return?[UIImage?imageNamed:@"5StarsSmall"];?
  • ????}?
  • ????return?nil;?
  • }?
  • 把tableView:cellForRowAtIndexPath: 改成:
  • -?(UITableViewCell?*)tableView:(UITableView?*)tableView?cellForRowAtIndexPath:(NSIndexPath?*)indexPath?
  • {?
  • ????UITableViewCell?*cell?=?[tableView?dequeueReusableCellWithIdentifier:@"PlayerCell"];?
  • ??
  • ????Player?*player?=?(self.players)[indexPath.row];?
  • ??
  • ????UILabel?*nameLabel?=?(UILabel?*)[cell?viewWithTag:100];?
  • ????nameLabel.text?=?player.name;?
  • ??
  • ????UILabel?*gameLabel?=?(UILabel?*)[cell?viewWithTag:101];?
  • ????gameLabel.text?=?player.game;?
  • ??
  • ????UIImageView?*ratingImageView?=?(UIImageView?*)[cell?viewWithTag:102];?
  • ????ratingImageView.image?=?[self?imageForRating:player.rating];?
  • ??
  • ????return?cell;?
  • }?
  • 下面運(yùn)行app ,效果如下: 哎呦~,看起來(lái)不怎么對(duì)哈,這些cell 都重疊在一起了,你只改變了prototype cell的高度,但是并沒(méi)有把table view考慮進(jìn)去。這里有2個(gè)解決方案,1 改變tableview 的Row Height 屬性或者執(zhí)行tableView:heightForRowAtIndexPath: 注意:你可能需要hightForRowAtIndexPath,如果你不知道你的cell的具體高度,或者不同的行有不同的高度。 . 回到Main.storyboard,在Table View 的Size inspector?設(shè)置Row Height 為55: 再運(yùn)行app,看起來(lái)好多了。 順路說(shuō)一嘴,當(dāng)你通過(guò)拖拽cell下沿的方式而不是直接設(shè)置值的方式去改變cell的高度,那么table view 的row 高度屬性自動(dòng)會(huì)變,當(dāng)你第一次這么做的使用它就會(huì)好用。 Using a Subclass for the Cell 這個(gè)table view 已經(jīng)看起來(lái)相當(dāng)不錯(cuò)了,但我對(duì)于通過(guò)tag 去獲取 label 或者 這個(gè)cell 的其他子視圖不感冒,把這些labels 與類(lèi)的outlet連接起來(lái)并使用相應(yīng)性應(yīng)該是更好的方式,事實(shí)證明你可以。通過(guò)Objective-C class template為項(xiàng)目添加一個(gè)新文件,命名為PlayerCell,并使它繼承自,繼承自UITableViewCell:
  • @interface?PlayerCell?:?UITableViewCell?
  • ??
  • @property?(nonatomic,?weak)?IBOutlet?UILabel?*nameLabel;?
  • @property?(nonatomic,?weak)?IBOutlet?UILabel?*gameLabel;?
  • @property?(nonatomic,?weak)?IBOutlet?UIImageView?*ratingImageView;?
  • ??
  • @end?
  • 這個(gè)類(lèi)本身并沒(méi)有做什么事情,僅僅是增加了幾個(gè)屬性nameLabel,gameLabel以及ratingImageView ,并且是Outlets。 回到Main.storyboard,選中prototype cell,并在Identity inspector中把它的class改成PlayerCell?。現(xiàn)在無(wú)論什么時(shí)候你通過(guò)dequeueReusableCellWithIdentifier向tableview請(qǐng)求一個(gè)新的cell 時(shí),它會(huì)返回PlayerCell?實(shí)例而不是?UITableViewCell?。 注意:這里我們把類(lèi)名跟reuse identifier 設(shè)置成一樣了,PlayerCell 這只是我的習(xí)慣而已,類(lèi)名跟reuse identifier 并沒(méi)有什么關(guān)系,所以如果你想起不一樣的,隨你好了。 下面連接 labels 以及 imageview 的outlet,選擇label的onnections inspector 中的New Referencing Outlet 拖拽到 table view cell 上,分別選中nameLabel ,gameLabel: 重點(diǎn):你需要把controls 與table view cell連接起來(lái),而不是視圖控制器。當(dāng)你的data source 要求那個(gè)table view 通過(guò)dequeueReusableCellWithIdentifier 要一個(gè)新的cell 的時(shí)候,table view 并不是給你一個(gè)真實(shí)的prototype cell,而是復(fù)制一份給你(或者重用之前那些cell中一個(gè)也說(shuō)不定)。這就意味著在同一時(shí)間不止有一個(gè)PlayerCell ?的實(shí)例。然后不同的label 拷貝視圖訪問(wèn)一個(gè)outlet,這是自找麻煩(從另一方面,把prototype cell 的 actions連接到 視圖控制器上是可行的,當(dāng)你的cell 中有自定義按鈕或者是其他繼承于UIControls ) 現(xiàn)在你已經(jīng)連接好這些屬性了,你只需要寫(xiě)點(diǎn)點(diǎn)data source代碼。首先在PlayersViewController.m中引入PlayerCell 類(lèi):
  • #import?"PlayerCell.h"?
  • 然后把cellForRowAtIndexPath 改為:
  • -?(UITableViewCell?*)tableView:(UITableView?*)tableView?cellForRowAtIndexPath:(NSIndexPath?*)indexPath?
  • {?
  • ????PlayerCell?*cell?=?(PlayerCell?*)[tableView?dequeueReusableCellWithIdentifier:@"PlayerCell"];?
  • ??
  • ????Player?*player?=?(self.players)[indexPath.row];?
  • ????cell.nameLabel.text?=?player.name;?
  • ????cell.gameLabel.text?=?player.game;?
  • ????cell.ratingImageView.image?=?[self?imageForRating:player.rating];?
  • ??
  • ????return?cell;?
  • }?
  • 更喜歡它了吧,現(xiàn)在你通過(guò)dequeueReusableCellWithIdentifier ?獲取PlayerCell的實(shí)例,然后可以設(shè)置 它的 labels 以及 imageview。 運(yùn)行應(yīng)用,它看起來(lái)跟之前沒(méi)什么不同,但是要注意到,你現(xiàn)在已經(jīng)用的是自定義的tableviewcell 的子類(lèi)了。 何去何從? 點(diǎn)擊查看該教程的第二部分,它涵蓋了segues,靜態(tài)table view cells以及下載示例工程等。

    總結(jié)

    以上是生活随笔為你收集整理的storyboard 使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。