多重MVC
简单多页面布局
我们首先创建多一个MVC,这一个MVC允许用户可以点选相应表情的按钮,然后跳转到表情页面。
创建新的MVC方法很简单,只需要在storyboard拖拽View Controller到空白的区域就可以了。创新新的MVC也要自己创建一个相应的Controller类。然后记得在inspector那里设置绑定相应的类。
之后我们来把选择页面建立好,简单使用4个按钮就好了。
现在我们来玩一下上一次的三种布局。
- Tab Bar
ctrl可以建立这个联系,选择view controller。
记得修改bar的内容要在对应页面的controller而不是tab bar controller哦。
- split view controller
这个也是很简单的,关键是在连接的时候一个链接选择master,一个是detail。
- segue
创建segue的方法也很简单,其实和超链接有点像。只需要把相应的按钮ctrl拉到要跳转至的页面,选择相应的segue方式就好了。
show 和 show detail的区别在于,是否有返回上一视图的按钮。实际上 ,show是将新的视图控件push到视图堆栈的顶端予以显示,然后通过按键pop返回上一视图。show detail 是用新的视图替换原始图,所以没有返回按钮,也无法返回。
然后我们需要设置identifier,来表示到底是谁在喊话。
紧接着我们来写segue发生时,跳转到新的mvc之前准备操作的代码。我们来看看xcode为我们准备好的segue函数。
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {}
sender显示的是呼叫segue的对象,就是刚刚定义的identifier。
首先我们要做的事情是拿到目标的ViewController。然后把这个原始的UIViewController转换成FaceViewController。
let destinationVC = segue.destination
if let faceVC = destinationVC as? FaceViewController{}
之后需要做的事情就是匹配相应的identifier然后把这个值通过viewcontroller来传给view就好了。
技巧:多种情况分类用字典。
private let emotionalFaces: Dictionary<String, FacialExpressionModel> = [
"happy": FacialExpressionModel(eye: .open, mouth: .smile, eyebrow: .happy),
"calm": FacialExpressionModel(eye: .open, mouth: .relax, eyebrow: .relax),
"quiet": FacialExpressionModel(eye: .close, mouth: .relax, eyebrow: .relax),
"sad": FacialExpressionModel(eye: .close, mouth: .sad, eyebrow: .sad)
]
可是运行之后居然会报错!!错误类型显示的是没有unwrap一个optional value。原来,在准备的时候,目标的view的指针还没有生成,而我们是默认把他unwrap了,所以是不对的。使用一个简单的if就可以修复了。
这里告诉我们一个很重要的设计思想,就是在我们初始化model以及outlet的时候,都要调用一次更新ui的函数,否则就会出现问题。
- navigation controller
现在我们可以尝试使用这一方式在iphone是适配。要把一个已经做好的scene变成navigation controller控制也是很容易的。只需要embed in 就可以了。一切都自动生成了!
但是这样运行会报错,断点检查发现是因为segue捕捉到的对象不再是view controller,是成为了navigation controller。所以解决的办法就是加多一个条件判断,如果不抓到的是navigation controller,那么就要进去抓去其中的visibleViewController。
if let navigation = destinationVC as? UINavigationController{
destinationVC = navigation.visibleViewController!
}
最后可以动态修改目标的MVC的navigation bar上面的title,方法如下:
if let button = sender as? UIButton{
faceVC.navigationItem.title = button.currentTitle
}
view controller lifetime cycle
一个完整的cycle会经历以下这些阶段:
细化分有如下这些:
有这些函数可以帮助我们,首先是viewDidLoad。
这里可以放入大部分的初始化代码,这个时候outlet已经生成了。
还有就是viewWillAppear,这里最好放开销高的东西放在这里(比如多线程)。
还有viewDidAppear,这里可以放入动画。
同样的会有viewWillDisappear来把viewDidAppear还原。
viewDidDisappear可以释放各种资源。