最近比较悠闲,就把之前学习的过程记录下吧,多少年后若是能在互联网上找到本身的痕迹,想一想仍是一件蛮值得高兴的事情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用法仍是同样的,只不过增长了一些确实特别好用的东西。不管什么方法,用到好就行。黑猫白猫,逮到老鼠就是好猫
一块儿学习吧。。。