版本記錄
版本號(hào) | 時(shí)間 |
---|---|
V1.0 | 2019.09.18 星期三 |
前言
iOS中有關(guān)視圖控件用戶(hù)能看到的都在UIKit框架里面,用戶(hù)交互也是通過(guò)UIKit進(jìn)行的渺贤。感興趣的參考上面幾篇文章雏胃。
1. UIKit框架(一) —— UIKit動(dòng)力學(xué)和移動(dòng)效果(一)
2. UIKit框架(二) —— UIKit動(dòng)力學(xué)和移動(dòng)效果(二)
3. UIKit框架(三) —— UICollectionViewCell的擴(kuò)張效果的實(shí)現(xiàn)(一)
4. UIKit框架(四) —— UICollectionViewCell的擴(kuò)張效果的實(shí)現(xiàn)(二)
5. UIKit框架(五) —— 自定義控件:可重復(fù)使用的滑塊(一)
6. UIKit框架(六) —— 自定義控件:可重復(fù)使用的滑塊(二)
7. UIKit框架(七) —— 動(dòng)態(tài)尺寸UITableViewCell的實(shí)現(xiàn)(一)
8. UIKit框架(八) —— 動(dòng)態(tài)尺寸UITableViewCell的實(shí)現(xiàn)(二)
9. UIKit框架(九) —— UICollectionView的數(shù)據(jù)異步預(yù)加載(一)
10. UIKit框架(十) —— UICollectionView的數(shù)據(jù)異步預(yù)加載(二)
11. UIKit框架(十一) —— UICollectionView的重用、選擇和重排序(一)
12. UIKit框架(十二) —— UICollectionView的重用志鞍、選擇和重排序(二)
13. UIKit框架(十三) —— 如何創(chuàng)建自己的側(cè)滑式面板導(dǎo)航(一)
14. UIKit框架(十四) —— 如何創(chuàng)建自己的側(cè)滑式面板導(dǎo)航(二)
15. UIKit框架(十五) —— 基于自定義UICollectionViewLayout布局的簡(jiǎn)單示例(一)
16. UIKit框架(十六) —— 基于自定義UICollectionViewLayout布局的簡(jiǎn)單示例(二)
17. UIKit框架(十七) —— 基于自定義UICollectionViewLayout布局的簡(jiǎn)單示例(三)
18. UIKit框架(十八) —— 基于CALayer屬性的一種3D邊欄動(dòng)畫(huà)的實(shí)現(xiàn)(一)
19. UIKit框架(十九) —— 基于CALayer屬性的一種3D邊欄動(dòng)畫(huà)的實(shí)現(xiàn)(二)
20. UIKit框架(二十) —— 基于UILabel跑馬燈類(lèi)似效果的實(shí)現(xiàn)(一)
21. UIKit框架(二十一) —— UIStackView的使用(一)
22. UIKit框架(二十二) —— 基于UIPresentationController的自定義viewController的轉(zhuǎn)場(chǎng)和展示(一)
23. UIKit框架(二十三) —— 基于UIPresentationController的自定義viewController的轉(zhuǎn)場(chǎng)和展示(二)
24. UIKit框架(二十四) —— 基于UICollectionViews和Drag-Drop在兩個(gè)APP間的使用示例 (一)
25. UIKit框架(二十五) —— 基于UICollectionViews和Drag-Drop在兩個(gè)APP間的使用示例 (二)
26. UIKit框架(二十六) —— UICollectionView的自定義布局 (一)
27. UIKit框架(二十七) —— UICollectionView的自定義布局 (二)
開(kāi)始
今天是個(gè)特殊的日子瞭亮,勿忘國(guó)恥,國(guó)人當(dāng)自強(qiáng)固棚,向抵抗侵略的將士們致敬统翩!
首先看下主要內(nèi)容
了解如何將iOS應(yīng)用程序拆分為兩個(gè)部分仙蚜,并在此
UISplitViewController
教程的每一側(cè)顯示視圖控制器
接著看一下寫(xiě)作環(huán)境
Swift 5, iOS 13, Xcode 11
應(yīng)用程序通常需要提供拆分視圖以提供整潔的導(dǎo)航模型。 這方面的一個(gè)例子是Mail.app
厂汗,它在iPad上使用左側(cè)有文件夾列表的分割視圖委粉,然后是右側(cè)選定的郵件項(xiàng)目。 Apple為我們構(gòu)建了一個(gè)非常方便的視圖控制器娶桦,稱(chēng)為UISplitViewController
贾节,它可以直接回到iPad
的低端。 在這個(gè)UISplitViewController
教程中衷畦,您將學(xué)習(xí)如何使用它栗涂! 此外,自iOS 8
起祈争,split view controller
拆分視圖控制器可在iPad
和iPhone
上運(yùn)行斤程。
在本教程中,您將從頭開(kāi)始創(chuàng)建一個(gè)通用應(yīng)用程序菩混,它使用split view controller
來(lái)顯示Math Ninja中的怪物列表暖释。
您將使用拆分視圖控制器來(lái)處理導(dǎo)航和顯示。 它適用于iPhone
和iPad
墨吓。
單擊File ? New ? Project…
,在Xcode中創(chuàng)建一個(gè)新項(xiàng)目纹磺。 選擇 iOS ? Application ? Single View App
模板帖烘。
將項(xiàng)目命名為MathMonsters
。 將Language
保持為Swift
橄杨。 將User Interface
設(shè)置為Storyboard
秘症。 取消選中所有復(fù)選框。 然后單擊Next
完成項(xiàng)目的創(chuàng)建式矫。
雖然您可以使用Master-Detail App
模板作為起點(diǎn)乡摹,但您將從頭開(kāi)始使用Single View App
模板。 這將使您更好地了解UISplitViewController
的工作原理采转。 在將來(lái)的項(xiàng)目中使用UISplitViewController
時(shí)聪廉,這些知識(shí)將非常有用。
是時(shí)候創(chuàng)建UI了故慈,所以打開(kāi)Main.storyboard
板熊。
刪除故事板中的默認(rèn)初始View Controller Scene
。 同時(shí)從項(xiàng)目導(dǎo)航器中刪除ViewController.swift
察绷,確保在詢(xún)問(wèn)時(shí)選擇Move to Trash
干签。
將拆分視圖控制器拖到空的故事板中:
這將為您的storyboard
添加幾個(gè)元素:
- Split View Controller - 拆分視圖控制器:此拆分視圖將包含應(yīng)用程序的其余部分,并且是應(yīng)用程序的根拆撼。
-
Navigation Controller - 導(dǎo)航控制器:此
UINavigationController
將是主視圖控制器的根視圖容劳。 這是拆分視圖的左側(cè)窗格喘沿,當(dāng)在iPad
上或在較大的iPhone(如iPhone 8 Plus)上橫向顯示時(shí)。在拆分視圖控制器中竭贩,您將看到導(dǎo)航控制器具有稱(chēng)為master view controller
的關(guān)系segue
蚜印。 這允許您在主視圖控制器中創(chuàng)建整個(gè)導(dǎo)航層次結(jié)構(gòu),而無(wú)需影響詳細(xì)視圖控制器娶视。 -
View Controller - 視圖控制器:這將最終顯示所有怪物的詳細(xì)信息晒哄。 如果查看拆分視圖控制器,您將看到視圖控制器具有稱(chēng)為詳細(xì)視圖控制器
(detail view controller)
的關(guān)系segue:
-
Table View Controller:這是主
UINavigationController
的根視圖控制器肪获。 它最終將顯示怪物列表寝凌。
注意:Xcode會(huì)警告您表視圖的原型單元缺少重用標(biāo)識(shí)符
(reuse identifier)
。 暫時(shí)不要擔(dān)心孝赫。 你很快就會(huì)解決它较木。
由于您從故事板中刪除了默認(rèn)的初始視圖控制器,因此您需要告訴故事板您希望拆分視圖控制器成為初始視圖控制器青柄。
選擇Split View Controller
伐债,然后打開(kāi)Attributes inspector
。 選中Is Initial View Controller
選項(xiàng)致开。
您將在分割視圖控制器的左側(cè)看到一個(gè)箭頭峰锁。 這告訴你它是這個(gè)故事板的初始視圖控制器。
在iPad模擬器上構(gòu)建并運(yùn)行應(yīng)用程序双戳。 將模擬器旋轉(zhuǎn)到橫向虹蒋。
您應(yīng)該看到一個(gè)空的拆分視圖控制器:
現(xiàn)在可以在任何iPhone
模擬器上運(yùn)行它,除了一個(gè)加大尺寸的手機(jī)飒货,它足夠大魄衅,可以像iPad一樣運(yùn)行。 你會(huì)看到它開(kāi)始全屏顯示細(xì)節(jié)視圖塘辅。 它還允許您點(diǎn)擊導(dǎo)航欄上的后退按鈕以彈回主視圖控制器:
在除了橫向大型Plus
或Max
設(shè)備之外的iPhone
上晃虫,分割視圖控制器將像傳統(tǒng)的master-detail
應(yīng)用程序一樣,帶有導(dǎo)航控制器來(lái)回推出和彈出扣墩。這是內(nèi)置功能哲银,開(kāi)發(fā)人員只需要很少的額外配置。
您需要顯示自己的視圖控制器而不是這些默認(rèn)控制器呻惕。是時(shí)候開(kāi)始創(chuàng)建它們了盘榨。
Creating Custom View Controllers
故事板具有視圖控制器層次結(jié)構(gòu)集:拆分視圖控制器,其主視圖控制器和詳細(xì)視圖控制器作為其子視圖◇∪冢現(xiàn)在草巡,您需要實(shí)現(xiàn)代碼方面以獲取要顯示的數(shù)據(jù)。
轉(zhuǎn)到File ? New ? File…
,并選擇iOS ? Source ? Cocoa Touch Class
模板山憨。將類(lèi)命名為MasterViewController
查乒,并使其成為UITableViewController
的子類(lèi)。確保未選中Also create XIB file
復(fù)選框郁竟,并將Language
設(shè)置為Swift
玛迄。單擊Next
,然后單擊Create
棚亩。
打開(kāi)MasterViewController.swift
蓖议。
向下滾動(dòng)到numberOfSections(in:)
中。刪除此方法讥蟆。只返回一個(gè)部分時(shí)不需要它勒虾。
接下來(lái),找到tableView(_:numberOfRowsInSection :)
并用以下內(nèi)容替換實(shí)現(xiàn):
override func tableView(
_ tableView: UITableView,
numberOfRowsInSection section: Int)
-> Int {
return 10
}
最后瘸彤,取消注釋tableView(_:cellForRowAt :)
并將其實(shí)現(xiàn)替換為以下內(nèi)容:
override func tableView(
_ tableView: UITableView,
cellForRowAt indexPath: IndexPath)
-> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
return cell
}
這樣修然,當(dāng)你稍后測(cè)試這個(gè)東西時(shí),你將看到十個(gè)空行质况。
打開(kāi)Main.storyboard
愕宋。 選擇Root View Controller
并切換Identity
檢查器。 將類(lèi)更改為MasterViewController
结榄。
此外中贝,您需要確保在表視圖中為原型單元格提供重用標(biāo)識(shí)符。 如果沒(méi)有臼朗,它會(huì)在故事板試圖加載時(shí)導(dǎo)致崩潰邻寿。
在Master View Controller
中,選擇Prototype Cell
依溯。 在Attributes inspector
中,將Identifier
更改為Cell
瘟则。 同時(shí)將單元格Style
更改為Basic
黎炉。
在iPad
或iPhone
模擬器中構(gòu)建和運(yùn)行。 你會(huì)注意到雖然有十行醋拧,都標(biāo)有標(biāo)題慷嗜,點(diǎn)擊一行不會(huì)做任何事情。 這是因?yàn)槟形粗付ㄔ敿?xì)視圖控制器丹壕。
現(xiàn)在庆械,您將為細(xì)節(jié)方創(chuàng)建視圖控制器。
轉(zhuǎn)到File ? New ? File…
菌赖,并選擇iOS ? Source ? Cocoa Touch Class
模板缭乘。 將類(lèi)命名為DetailViewController
,并使其成為UIViewController
的子類(lèi)琉用。 確保未選中Also create XIB file
復(fù)選框堕绩,并將Language
設(shè)置為Swift
策幼。
單擊Next
,然后單擊Create
奴紧。
打開(kāi)Main.storyboard
并在View Controller Scene
中選擇視圖控制器特姐。 在Identity inspector
中,將Class
更改為DetailViewController
黍氮。
然后將label
拖到詳細(xì)視圖控制器的中間唐含。 使用“自動(dòng)布局”將label
固定到容器的水平和垂直中心。
雙擊label
將其文本更改為Hello沫浆,World捷枯!
,所以當(dāng)你稍后測(cè)試它時(shí)你會(huì)知道它正在工作件缸。
構(gòu)建并運(yùn)行铜靶。 此時(shí),您應(yīng)該看到自定義視圖控制器他炊。
在iPad
上:
在iPhone
上:
您現(xiàn)在已經(jīng)獲得了拆分視圖的基礎(chǔ)争剿,每個(gè)位都有自定義視圖控制器。 接下來(lái)你需要添加那些討厭的怪物痊末。
Making Your Model
接下來(lái)蚕苇,您需要為要顯示的數(shù)據(jù)定義模型。 在學(xué)習(xí)拆分視圖控制器的基礎(chǔ)知識(shí)時(shí)凿叠,您不希望復(fù)雜化涩笤,因此您將使用沒(méi)有數(shù)據(jù)持久性的簡(jiǎn)單模型。
首先盒件,創(chuàng)建一個(gè)表示要顯示的怪物的類(lèi)蹬碧。 轉(zhuǎn)到File ? New ? File…
,選擇iOS ? Source ? Swift File
模板炒刁,然后單擊Next
恩沽。 將文件命名為Monster
,然后單擊Create
翔始。
您將創(chuàng)建一個(gè)簡(jiǎn)單的類(lèi)罗心,其中包含有關(guān)要顯示的每個(gè)怪物的屬性屬性。 您還將實(shí)現(xiàn)一些方法來(lái)創(chuàng)建新的怪物并訪問(wèn)每個(gè)怪物武器的圖像城瞎。
用以下內(nèi)容替換Monster.swift
的內(nèi)容:
import UIKit
enum Weapon {
case blowgun, ninjaStar, fire, sword, smoke
var image: UIImage {
switch self {
case .blowgun:
return UIImage(named: "blowgun.png")!
case .fire:
return UIImage(named: "fire.png")!
case .ninjaStar:
return UIImage(named: "ninjastar.png")!
case .smoke:
return UIImage(named: "smoke.png")!
case .sword:
return UIImage(named: "sword.png")!
}
}
}
class Monster {
let name: String
let description: String
let iconName: String
let weapon: Weapon
init(name: String, description: String, iconName: String, weapon: Weapon) {
self.name = name
self.description = description
self.iconName = iconName
self.weapon = weapon
}
var icon: UIImage? {
return UIImage(named: iconName)
}
}
這定義了枚舉和類(lèi)渤闷。 枚舉是為了跟蹤不同種類(lèi)的武器,包括每種武器的圖像脖镀。 該類(lèi)將使用簡(jiǎn)單的初始化程序保存怪物信息以創(chuàng)建Monster
實(shí)例飒箭。
這是用于定義模型的。 接下來(lái),您將它連接到您的主視圖补憾!
Displaying the Monster List
打開(kāi)MasterViewController.swift
并向該類(lèi)添加一個(gè)新屬性:
let monsters = [
Monster(name: "Cat-Bot", description: "MEE-OW",
iconName: "meetcatbot", weapon: .sword),
Monster(name: "Dog-Bot", description: "BOW-WOW",
iconName: "meetdogbot", weapon: .blowgun),
Monster(name: "Explode-Bot", description: "BOOM!",
iconName: "meetexplodebot", weapon: .smoke),
Monster(name: "Fire-Bot", description: "Will Make You Steamed",
iconName: "meetfirebot", weapon: .ninjaStar),
Monster(name: "Ice-Bot", description: "Has A Chilling Effect",
iconName: "meeticebot", weapon: .fire),
Monster(name: "Mini-Tomato-Bot", description: "Extremely Handsome",
iconName: "meetminitomatobot", weapon: .ninjaStar)
]
這可以保存用于填充表視圖的怪物數(shù)組漫萄。
找到tableView(_:numberOfRowsInSection :)
并將return
語(yǔ)句替換為以下內(nèi)容:
return monsters.count
這將根據(jù)數(shù)組的大小返回怪物數(shù)量。
接下來(lái)盈匾,找到tableView(_:cellForRowAtIndexPath :)
并在最終的return
語(yǔ)句之前添加以下代碼:
let monster = monsters[indexPath.row]
cell.textLabel?.text = monster.name
這將根據(jù)正確的怪物配置單元格腾务。 這就是table view
,它只是顯示每個(gè)怪物的名字削饵。
構(gòu)建并運(yùn)行應(yīng)用程序岩瘦。
你應(yīng)該在橫屏iPad
的左側(cè)看到怪物機(jī)器人列表:
在iPhone
上:
請(qǐng)記住,在compact-width
的iPhone
上窿撬,您可以在詳細(xì)信息屏幕上的導(dǎo)航堆棧中開(kāi)始一層深度启昧。 您可以點(diǎn)擊后退按鈕查看table view
。
Updating the Master View Controller’s Title
導(dǎo)航欄自動(dòng)設(shè)置初始視圖控制器的標(biāo)題劈伴,即RootViewController
密末。
打開(kāi)Main.storyboard
,選擇Root View Controller
并雙擊NavigationBar
跛璧。
將其更改為Monster List
严里。 這比Root View Controller
好得多。
Displaying Bot Details
現(xiàn)在table view
顯示了怪物列表追城,現(xiàn)在是時(shí)候按順序獲取詳細(xì)視圖了刹碾。
打開(kāi)Main.storyboard
,選擇Detail View Controller
并刪除之前放下的label
座柱。
使用下面的屏幕截圖作為指導(dǎo)迷帜,將以下控件拖到DetailViewController
的視圖中(有關(guān)要添加的內(nèi)容的詳細(xì)列表,請(qǐng)參閱下面的內(nèi)容):
以下是您需要添加的內(nèi)容:
- 1) 其余視圖將進(jìn)入的容器視圖色洞。這應(yīng)該與屏幕頂部對(duì)齊并在屏幕中水平居中戏锹。
- 2) 一個(gè)
95×95
的圖像視圖,距離容器視圖頂部8
個(gè)像素火诸,距離左側(cè)20
個(gè)像素锦针。這是為了顯示怪物的圖像。 - 3) 與圖像視圖頂部對(duì)齊的
label
惭蹂,字體System Bold
伞插,大小為30
割粮,文本為Monster Name
盾碗。將其頂部與圖像的頂部對(duì)齊,并將其設(shè)置為圖像右側(cè)的8
個(gè)像素舀瓢。同時(shí)使其尾部邊距容器視圖的右側(cè)8
像素廷雅。 - 4) 下面有兩個(gè)帶有
System
字體的labels
,尺寸為24
。一個(gè)label
應(yīng)與圖像視圖底部對(duì)齊航缀。另一個(gè)label
應(yīng)位于第一個(gè)標(biāo)簽下方商架。它們的左邊緣應(yīng)該對(duì)齊,它們應(yīng)該垂直間隔8個(gè)像素芥玉。同時(shí)將這些標(biāo)簽的尾部設(shè)置為距離容器視圖右側(cè)8個(gè)像素蛇摸。他們應(yīng)該有標(biāo)題Description
和Preferred way to kill
。 - 5) 一個(gè)
70×70
的圖像視圖灿巧,與Preferred way to kill
標(biāo)簽左對(duì)齊赶袄,8像素垂直間距。同時(shí)將其底部設(shè)置為距離容器視圖底部8個(gè)像素抠藕。
讓自動(dòng)布局使用適當(dāng)?shù)募s束尤其重要饿肺,因?yàn)檫@個(gè)應(yīng)用程序是通用的,自動(dòng)布局確保布局適應(yīng)iPad和iPhone盾似。
這就是現(xiàn)在的自動(dòng)布局敬辣。 接下來(lái),您需要將這些視圖掛鉤到某些outlets
零院。
打開(kāi)DetailViewController.swift
并將以下屬性添加到類(lèi)的頂部:
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var descriptionLabel: UILabel!
@IBOutlet weak var iconImageView: UIImageView!
@IBOutlet weak var weaponImageView: UIImageView!
var monster: Monster? {
didSet {
refreshUI()
}
}
在這里溉跃,您為剛剛創(chuàng)建的需要?jiǎng)討B(tài)更改的各種UI元素添加了屬性。 您還為此視圖控制器應(yīng)顯示的Monster
對(duì)象添加了一個(gè)屬性门粪。
接下來(lái)喊积,將以下幫助器方法添加到類(lèi)中:
private func refreshUI() {
loadViewIfNeeded()
nameLabel.text = monster?.name
descriptionLabel.text = monster?.description
iconImageView.image = monster?.icon
weaponImageView.image = monster?.weapon.image
}
無(wú)論何時(shí)切換怪物,您都希望UI自行刷新并更新outlets
中顯示的詳細(xì)信息玄妈。 你甚至可以在視圖加載之前更改monster
并觸發(fā)方法乾吻。 因此,您調(diào)用loadViewIfNeeded()
以保證視圖已加載且其outlets
已連接拟蜻。
現(xiàn)在绎签,打開(kāi)Main.storyboard
。 在Document Outline
中右鍵單擊Detail View Controller
對(duì)象以顯示插座列表酝锅。 從每個(gè)項(xiàng)目右側(cè)的圓圈拖動(dòng)到視圖以連接outlets
诡必。
請(qǐng)記住,圖標(biāo)圖像視圖是左上角的大圖像視圖搔扁。 武器圖像視圖是Preferred way to kill
標(biāo)簽的方式下面較小的一個(gè)爸舒。
轉(zhuǎn)到SceneDelegate.swift
并使用以下內(nèi)容替換scene(_:willConnectTo:options :)
的實(shí)現(xiàn):
guard
let splitViewController = window?.rootViewController as? UISplitViewController,
let leftNavController = splitViewController.viewControllers.first
as? UINavigationController,
let masterViewController = leftNavController.viewControllers.first
as? MasterViewController,
let detailViewController = splitViewController.viewControllers.last
as? DetailViewController
else { fatalError() }
let firstMonster = masterViewController.monsters.first
detailViewController.monster = firstMonster
拆分視圖控制器具有一個(gè)數(shù)組屬性viewControllers
,其中包含主控制器和詳細(xì)視圖控制器稿蹲。 在您的情況下扭勉,主視圖控制器實(shí)際上是導(dǎo)航控制器。 因此苛聘,要獲取實(shí)際的MasterViewController
實(shí)例涂炎,請(qǐng)使用導(dǎo)航控制器的第一個(gè)視圖控制器忠聚。
要獲取詳細(xì)視圖控制器,請(qǐng)查看拆分視圖控制器的viewControllers
數(shù)組中的第二個(gè)視圖控制器唱捣。
構(gòu)建并運(yùn)行應(yīng)用程序两蟀,您應(yīng)該在右側(cè)看到一些怪物細(xì)節(jié)。
在iPad
上橫屏:
在iPhone
上
請(qǐng)注意震缭,在MasterViewController
上選擇一個(gè)monster
什么也沒(méi)做赂毯,你就永遠(yuǎn)陷入了Cat-Bot
。 這就是你接下來(lái)要做的事情拣宰!
Hooking Up the Master With the Detail
關(guān)于如何在這兩個(gè)視圖控制器之間進(jìn)行最佳通信的策略有很多欢瞪。 在Master-Detail App
模板中,主視圖控制器具有對(duì)詳細(xì)視圖控制器的引用徐裸。 這意味著主視圖控制器可以在選擇行時(shí)在詳細(xì)視圖控制器上設(shè)置屬性遣鼓。
這適用于在詳細(xì)信息窗格中只有一個(gè)視圖控制器的簡(jiǎn)單應(yīng)用程序。 但是重贺,您將遵循UISplitViewController
類(lèi)引用中建議的方法來(lái)處理更復(fù)雜的應(yīng)用程序并使用委托delegate
骑祟。
打開(kāi)MasterViewController.swift
并在MasterViewController
類(lèi)定義上面添加以下協(xié)議定義:
protocol MonsterSelectionDelegate: class {
func monsterSelected(_ newMonster: Monster)
}
這定義了一個(gè)帶有單個(gè)方法的協(xié)議,monsterSelected(_ :)
气笙。 詳細(xì)視圖控制器將實(shí)現(xiàn)此方法次企,并且主視圖控制器將在用戶(hù)選擇怪物時(shí)向其發(fā)送消息。
接下來(lái)潜圃,更新MasterViewController
以添加符合委托協(xié)議的對(duì)象的屬性:
weak var delegate: MonsterSelectionDelegate?
基本上缸棵,這意味著委托屬性需要是一個(gè)實(shí)現(xiàn)了monsterSelected(_ :)
的對(duì)象。 在用戶(hù)選擇怪物后谭期,該對(duì)象將負(fù)責(zé)處理其視圖中需要發(fā)生的事情堵第。
由于您希望DetailViewController
在用戶(hù)選擇怪物時(shí)更新,因此您需要實(shí)現(xiàn)委托隧出。
打開(kāi)DetailViewController.swift
并在文件的最后添加一個(gè)類(lèi)擴(kuò)展:
extension DetailViewController: MonsterSelectionDelegate {
func monsterSelected(_ newMonster: Monster) {
monster = newMonster
}
}
類(lèi)擴(kuò)展非常適合分離委托協(xié)議并將方法組合在一起踏志。 在此擴(kuò)展中,您說(shuō)DetailViewController
符合MonsterSelectionDelegate
胀瞪。 然后针余,您實(shí)現(xiàn)一個(gè)必需的方法。
現(xiàn)在委托方法已準(zhǔn)備就緒凄诞,您需要從master
方面調(diào)用它圆雁。
打開(kāi)MasterViewController.swift
并添加以下方法:
override func tableView(
_ tableView: UITableView,
didSelectRowAt indexPath: IndexPath) {
let selectedMonster = monsters[indexPath.row]
delegate?.monsterSelected(selectedMonster)
}
實(shí)現(xiàn)tableView(_:didSelectRowAt :)
意味著只要用戶(hù)在表視圖中選擇一行,您就會(huì)收到通知帆谍。 您需要做的就是通知新怪物的怪物選擇代理伪朽。
最后,返回SceneDelegate.swift
既忆。 在scene(_:willConnectTo:options:)
中驱负,在方法的最后添加以下代碼:
masterViewController.delegate = detailViewController
這是兩個(gè)視圖控制器之間的最終連接。
在iPad
上構(gòu)建并運(yùn)行應(yīng)用程序患雇。 你現(xiàn)在應(yīng)該可以在monsters
之間進(jìn)行選擇跃脊,如下所示:
到目前為止,拆分視圖非常好苛吱! 但是還有一個(gè)問(wèn)題:如果你在iPhone
上運(yùn)行它酪术,從主表視圖中選擇怪物不會(huì)顯示詳細(xì)視圖控制器。 您現(xiàn)在需要進(jìn)行一些小修改翠储,以確保拆分視圖也適用于iPhone绘雁。
打開(kāi)MasterViewController.swift
。 找到tableView(_:didSelectRowAt :)
并將以下內(nèi)容添加到方法的末尾:
if let detailViewController = delegate as? DetailViewController {
splitViewController?.showDetailViewController(detailViewController, sender: nil)
}
首先援所,您需要確保代理已設(shè)置庐舟,并且它是一個(gè)DetailViewController
實(shí)例,正如您所期望的那樣住拭。 然后在拆分視圖控制器上調(diào)用showDetailViewController(_:sender :)
并傳入詳細(xì)視圖控制器挪略。 UIViewController
的每個(gè)子類(lèi)都有一個(gè)繼承屬性splitViewController
,它將引用它容器視圖控制器(如果存在)滔岳。
此新代碼僅更改iPhone
上應(yīng)用程序的行為杠娱,導(dǎo)致導(dǎo)航控制器在您選擇新怪物時(shí)將細(xì)節(jié)控制器推入堆棧。 它不會(huì)改變iPad
實(shí)現(xiàn)的行為谱煤,因?yàn)樵趇Pad上摊求,細(xì)節(jié)視圖控制器始終可見(jiàn)。
進(jìn)行此更改后刘离,在iPhone上運(yùn)行它現(xiàn)在應(yīng)該正常運(yùn)行室叉。 只需添加幾行代碼,您就可以在iPad和iPhone上使用功能齊全的分割視圖控制器硫惕。 不錯(cuò)太惠!
Split View Controller in iPad Portrait
以縱向模式在iPad
中運(yùn)行應(yīng)用程序。 起初疲憋,似乎沒(méi)有辦法進(jìn)入左側(cè)菜單凿渊。
但請(qǐng)嘗試從屏幕左側(cè)滑動(dòng)。 很酷吧缚柳? 點(diǎn)按菜單外的任意位置即可隱藏它埃脏。
內(nèi)置的滑動(dòng)功能非常酷秋忙,但是如果你想在導(dǎo)航欄上方放置一個(gè)顯示菜單的按鈕彩掐,類(lèi)似于它在iPhone
上的表現(xiàn)怎么辦? 要做到這一點(diǎn)灰追,您需要對(duì)應(yīng)用程序進(jìn)行一些小的修改堵幽。
首先狗超,打開(kāi)Main.storyboard
并將Detail View Controller
嵌入到導(dǎo)航控制器中。 您可以通過(guò)選擇詳細(xì)視圖控制器朴下,然后選擇Editor ? Embed In ? Navigation Controller
來(lái)完成此操作努咐。
您的故事板現(xiàn)在看起來(lái)像這樣:
現(xiàn)在打開(kāi)MasterViewController.swift
并找到tableView(_:didSelectRowAt :)
。 通過(guò)調(diào)用showDetailViewController(_:sender :)
將if
塊更改為以下內(nèi)容:
if
let detailViewController = delegate as? DetailViewController,
let detailNavigationController = detailViewController.navigationController {
splitViewController?
.showDetailViewController(detailNavigationController, sender: nil)
}
現(xiàn)在殴胧,您將顯示詳細(xì)視圖控制器的導(dǎo)航控制器渗稍,而不是顯示詳細(xì)視圖控制器。 無(wú)論如何团滥,導(dǎo)航控制器的根目錄是詳細(xì)視圖控制器竿屹,因此您仍然可以看到與之前相同的內(nèi)容,只需將其包含在導(dǎo)航控制器中灸姊。
在運(yùn)行應(yīng)用程序之前拱燃,最后要進(jìn)行兩項(xiàng)更改。
首先力惯,在SceneDelegate.swift
更新scene(_willConnectTo:options:)
中扼雏,通過(guò)替換初始化detailViewController
的行來(lái)解釋DetailViewController
現(xiàn)在包含在導(dǎo)航控制器中的事實(shí):
let detailViewController =
(splitViewController.viewControllers.last as? UINavigationController)?
.topViewController as? DetailViewController
由于詳細(xì)視圖控制器包含在導(dǎo)航控制器中,因此現(xiàn)在有兩個(gè)步驟來(lái)訪問(wèn)它夯膀。
最后诗充,在方法結(jié)束之前添加以下行。
detailViewController.navigationItem.leftItemsSupplementBackButton = true
detailViewController.navigationItem.leftBarButtonItem =
splitViewController.displayModeButtonItem
這告訴詳細(xì)視圖控制器用一個(gè)按鈕替換其左側(cè)導(dǎo)航項(xiàng)诱建,該按鈕將切換拆分視圖控制器的顯示模式蝴蜓。 在iPhone
上運(yùn)行時(shí)不會(huì)改變?nèi)魏螙|西,但在iPad
上俺猿,你會(huì)在左上角看到一個(gè)按鈕來(lái)切換table view
顯示茎匠。
在iPad
豎屏上運(yùn)行應(yīng)用程序并檢查:
現(xiàn)在,您可以在縱向和橫向上在iPad
和iPhone
上運(yùn)行良好的效果押袍!
后記
本篇主要講述了一個(gè)UISplitViewController的簡(jiǎn)單實(shí)用示例诵冒,感興趣的給個(gè)贊或者關(guān)注~~~