一、storyboard文件中viewController的跳转和传值
1.跳转
首先storyboard本身提供了很多便捷的方式帮助我们构建布局文件,直接可以通过“连线”操作就可以实现viewContoller之间的跳转,storyboard可以看作是一个页面集合或者viewController的集合。这样不仅可以减少我们编写的代码量,也方便我们查看页面之间的跳转逻辑,下面我简单地说一下,操作方式:
新建几个viewController,使用按住control和左键(触摸板按下去),拖动,就会出现一条带箭头的线,然后移动到你想要跳转的viewController中,释放它,就是出现几个action选项,一般选show即可
2.Action Segue区别
Segue分为以下几种类型,其中Push、Modal、Popover和Replace已弃用。
- Show
- Show Detail
- Present Modally
- Present as Popover
- Custom
PushModalPopoverReplace
Show
- 该方法为视图控制器提供了自适应、灵活的呈现方式。
- 用在UINavigationController堆栈视图时。目的地视图会被压入导航栈顶部。导航条提供一个后退按钮。
- 用在UIViewController实例时,和present()效果一致。
Show Detail
- 与Show相似,但会替换源视图,没有导航条和后退按钮。
Present Modally
- 使用方法present()
- 有多种不同呈现方式,可根据需要设置。在iPhone中,一般以动画的形式自下向上覆盖整个屏幕,用户无法与上一个视图交互,除非关闭当前视图;在iPad中,常见呈现为一个中心框,中心框以动画形式自下向上弹出,同时使底层视图控制器变暗。
- 不提供返回按钮。
Present as Popover
- 在iPad中,目标视图以浮动窗样式呈现,点击目标视图以外区域,目标视图消失;在iPhone中,默认目标视图以模态覆盖整个屏幕。
下面GIF演示了Show和Present在新页面出现方式的不同:
3.反向转场
Present Modally不提供返回按钮,需要定于“反向转场(unwind segue)”
在需要退出的控制器定于一个方法:此方法只有一个参数,类型必须是UIStoryboardSegue,且有修饰符@IBAction
@IBAction func close(segue:UIStoryboardSegue){
let vc = segue.source as! ReviewViewController
//反向传值
print(vc.data)
}
在Storyboard上指定反向转场关联
Ctrl拖到 关闭按钮 至视图的Exit,选择close:
4.传值
在第一个页面覆写prepare方法,在vc.message中填要传的数据。
//使用SB连接转场每次都会触发下面方法
override func prepare(segue: UIStoryboardSegue, sender: AnyObject?) {
//可再每个连线处类似按钮的东西加上identifier,即可判断不同指向
if segue.identifier == "segueIdentifier" {
//不带导航的方式
let vc = segue.destinationViewController as! nextVC
//下个视图前了带了导航的方式
//let nv_vc = segue.destinationViewController.childViewControllers[0] as! nextVC
vc.message = "传值"
}
}
二、不带任何布局文件的viewController之间的跳转
1.用在UIViewController实例
present()方法与dismiss()方法相对应。
//present方式
let vc = SecondViewController()
self.present(vc, animated: true, completion: nil)
//dismiss方式
self.dismiss(animated:true,completion:nil)
2.用在UINavigationController实例
pushViewController()方法与popViewController()方法相对应。
let viewController = ViewController()
self.navigationController?.pushViewController(viewController, animated:true)
返回上一个视图
self.navigationController?.popViewController(animated:true)
//使用匿名变量可以消除“返回值未使用”警告
_ = self.navigationController?.popViewController(animated:true)
返回到指定视图
//弹回根视图
self.navigationController?.popToRootViewControllerAnimated(true)
//指定位置
self.navigationController?.popToViewController((self.navigationController?.viewControllers[0])!, animated: true)
三、带Storyboard 界面的viewController之间的跳转
let sb = UIStoryboard(name: "Main", bundle:nil)
let vc = sb.instantiateViewControllerWithIdentifier("SecondViewController") as! SecondViewController
self.presentViewController(vc, animated: true, completion: nil)
注意:记得要设置 StoryboardID ,可以在 Identifier inspector 中修改
四、传值
正向传值
方式1
在第一个界面添加一个action
@IBAction func touch(_ sender:AnyObject){
let vc = ViewControllerTwo()
vc.data = "第一个界面传入的数据"
self.present(vc, animated:true, completion:nil)
}
在第二界面使用
override func viewDidLoad(){
super.viewDidLoad()
print(data)
}
方式2
给第二个界面定义一个新的构造方法
init(data:String){
self.data = data
super.init(nibName:nil, bundle:nil)
}
在第一个界面使用新的构造方法对ViewControllerTwo类进行实例化
@IBAction func touch(_ sender:AnyObject){
let vc = ViewControllerTwo(data:"第一个界面传入的数据")
self.present(vc, animated:true, completion:nil)
}
反向传值
反向传值比正向传值要复杂一些,在实际开发中通常使用协议或者闭包完成反向传值。
方式1使用协议
在第二个界面创建一个协议
protocol ViewControllerTwoProtocol {
func setData(data:String)
}
var delegate:ViewControllerTwoProtocol?
当点击返回按钮时,进行值得传递
func ret(){
delegate?.sentData(data:"第二个界面返回的值")
self.dismiss(animated:true, completion:nil)
}
第一个界面要遵守ViewControllerTwoProtocol协议,并实现协议的传值方法
class ViewController:UIViewController:UIViewController,ViewControllerTwoProtocol{
@IBAction func touch(_ sender:AnyObject){
let vc = ViewControllerTwo(data:"第一个界面传入的数据")
//设置代理
vc.delegate = self
self.present(vc, animated:true, completion:nil)
}
func sentData(data:String){
print(data)
}
}
方式2使用闭包
在第二个界面创建闭包,并传值
var closure:((String)->Void)?
func ret(){
self.closure!("第二个界面返回的值")
self.dismiss(animated:true, completion:nil)
}
第一个界面对闭包赋值
@IBAction func touch(_ sender:AnyObject){
let vc = ViewControllerTwo(data:"第一个界面传入的数据")
//设置代理
vc.closure = {(data:String) in
print(data)
}
self.present(vc, animated:true, completion:nil)
}