最近比較悠閒,就把之前學習的過程記錄下吧,多少年後若是能在互聯網上找到本身的痕跡,想一想仍是一件蠻值得高興的事情swift
容器在開發過程當中用到的地方仍是蠻多的,像網易新聞的框架若是使用代碼去實現的話,調用系統的APIbash
addChildViewController(<#T##childController: UIViewController##UIViewController#>)
複製代碼
使它成爲子控制器,加入一個相似的容器裏面就能夠,具體的你們在作項目過程當中都用到過,這裏就很少說了。今天就分享一下SB上使用容器類管理VC的控件ContainerView(純代碼裏沒有這個控件)閉包
新建個項目(這裏我使用的是之前本身隨便寫的一個小demo),在Manstoryboard 的 view 上拖拽兩個ContainerView ,給他們兩個分別設置約束,寬度加起來等於屏幕寬度就能夠。拖拽完後你會發現view上多出來兩根線而且關聯到兩個VC。其實這就是containerView 自帶的容器VC,它讓咱們能夠把代碼和業務都分發到一個獨立的VC裏面去操做,耦合性更低。框架
爲了後面的操做咱們須要在swift文件裏面給這兩個VC綁定兩個Class,取名爲Class1 和Class2 都繼承於BaseVC(BaseVC裏面只是簡單的對導航欄裏面的操做) 。而後要將ContainerView關聯的VC跟咱們swift文件裏面的類關聯起來,而且綁定它們的storyboardId ide
到如今的話,基本上容器的使用算是完成了,咱們想作的業務就能夠分別在兩個vc裏面實現了。可是這樣的話就太不直觀了,接着說個例子吧。學習
如今好多App 都有雙列表,比方說京東的ui
這個雙列表頁面,咱們就能使用ContainerView 來實現相似的效果。spa
首先咱們在Class1 和Class2 裏面各自添加兩個tableView 並給他們附上數據,最終的效果是這樣的代理
這個時候若是咱們想作數據的交互,就須要傳值。OC裏面的傳值方式有不少,通知,代理,block 等等,其實最簡單的就是使用NSNotificationCenter ,通知比較簡單,我就不說了,swift裏面的使用跟OC差很少。這裏說一下代理的用法和swift裏面閉包的用法code
先說下代理,由於咱們使用的是容器ContainerView 它會自帶兩個VC,又加上原來的一個VC,至關於三個VC,怎麼ContainerView裏面取到對應關聯的兩個VC,這是一個關鍵。
在承載連個ContainerView 的VC裏面重寫下面的方法
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
}
複製代碼
只須要重寫系統的這個方法,這個方法是SB裏面的視圖切換的時候系統會調用的一個方法,它的參數 segue.destination
let vc = segue.destination
複製代碼
返回的就是對應的ContainerView 自帶的VC
由於咱們使用了兩個VC 因此要判斷下是具體哪一個VC
var class1:Class1? = nil
var class2:Class2? = nil
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let vc = segue.destination as? Class1 {
class1 = vc
}
if let vc = segue.destination as? Class2 {
class2 = vc
}
}
複製代碼
取到這兩個VC後,就好辦多了。而後要作的無非就是聲明協議,遵循代理,實現代理方法
protocol XWContainerViewResponseDelegate {
func clickWithGetIndex(index:NSIndexPath)
}
複製代碼
聲明一個協議,參數爲NSIndexPath 類型,而後讓Class1 聲明一個代理屬性
var delegate:XWContainerViewResponseDelegate?
複製代碼
而後在Class1 tabviewVIew 的點擊方法裏面調用代理(不須要去調用responds(to: <#T##Selector!#>) delegate? 就至關於OC裏面的responds)
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
delegate?.clickWithGetIndex(index: (indexPath as? NSIndexPath)!)
}
複製代碼
而後讓Class2 去遵循協議,實現代理方法,這樣就OK了。可是不知道你們有沒有發現,OC使用的時候咱們通常都會設置
XXXX.delegate = XXXX
複製代碼
這一步咱們尚未寫,可是這Class1 和 Class2 又是獨立的,沒有關聯。因此這個時候咱們就要用到承載這兩個容器所在的VC了,在上面的那個方法裏面,咱們獲取到了這兩個VC,在這裏進行關聯
var class1:Class1? = nil
var class2:Class2? = nil
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let vc = segue.destination as? Class1 {
class1 = vc
}
if let vc = segue.destination as? Class2 {
class2 = vc
}
class1?.delegate = class2
}
複製代碼
OK,這樣就完整了,點擊Class1 的cell 就會把對應的IndexPath 傳過去,就能夠作操做了
在說下使用閉包傳值的作法 其實核心的地方都在承載兩個ContainerView 所在的VC裏面。由於咱們所作的操做是想點擊Class1 裏面的cell,把對方的Indexpath 給傳過去,那麼確定是想把IndexPath 給回調出去。回調出去以後Class2 怎麼去接受呢?其實Class2 也能夠有一個閉包專門去接受這個數據,可是這樣就太麻煩了。咱們能夠在Class2 裏面聲明一個屬性,去實現它的屬性觀察器方法,這樣就能隨時監聽這個屬性的變化,更方便的去作操做
首先在class1 裏面去聲明閉包,順便給它一個屬性去記錄所要傳遞的IndexPath
typealias CallBack = (_ index:NSIndexPath)->Void
var xwCallBack:CallBack?
var class1Index: NSIndexPath? = nil
複製代碼
Class2 裏面的操做 聲明屬性觀察器
var class2Index:NSIndexPath? = nil {
willSet {
}
didSet {
print("獲得的從1傳過來的值 \(String(describing: class2Index?.row))")
}
}
複製代碼
而後在Class1 cell的點擊方法裏面去調用它
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
xwCallBack!(indexPath as NSIndexPath)
}
複製代碼
ContainerView 承載所在的VC 讓Class1 實現閉包
var class1:Class1? = nil
var class2:Class2? = nil
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let vc = segue.destination as? Class1 {
class1 = vc
}
if let vc = segue.destination as? Class2 {
class2 = vc
}
unowned let weakSelf = self
class1?.xwCallBack = { index in
weakSelf.class2?.class2Index = index
}
}
複製代碼
而後把Class1傳過來的IndexPath 賦值給Class2的 帶有屬性觀察器的屬性。OK,這樣就能夠了
其實swift 裏面的東西 大體跟OC用法仍是同樣的,只不過增長了一些確實特別好用的東西。不管什麼方法,用到好就行。黑貓白貓,逮到老鼠就是好貓
一塊兒學習吧。。。