swift页面跳转

今天搞通了swift页面跳转。如果对比前端或者说web应用,其实就是“路由”,像react应用,可以通过react-router来管理路由,vue可以通过vue-router来管理路由类似,swift中可以用UINavigationController来管理“路由”,这里应该叫“导航”吧。iOS中有两种不同形式的跳转,一种是有逻辑层级关系的跳转,一种是临时页面的跳转。

具有逻辑层级关系的页面跳转

比如网上购物,下单之后要跳到订单页面,再跳到支付页面等等,这种跳转是有一定逻辑,或者说先后顺序的。这种跳转需要用NavigationViewController进行跳转。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//创建一个按钮,用来跳转页面
let btn = UIButton(frame: CGRect(x: 100, y: 80, width: 100, height: 45 ))
btn.setTitle("Next", for: .normal)
btn.backgroundColor = .blue
btn.addTarget(self, action: #selector(gotoNext), for: .touchUpInside)
self.view.addSubview(btn)
}
func gotoNext() {
let anotherView = HelloController() //要跳转到的页面
self.navigationController?.pushViewController(anotherView, animated: true)
}
}

上面的代码,使用navigationController下的pushViewController方法进行跳转。同时新建一个Cocoa Touch Class文件,然后选择subclass为UIViewController,文件名是上面代码用到的HelloController,这就是要跳转到的第二个页面。我们在这个页面放一个返回的按钮,跳回到原来的页面。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class HelloController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton()
button.frame = CGRect(x: 50, y: 80, width: 100, height: 45)
button.setTitle("Back", for: .normal)
button.backgroundColor = UIColor.cyan
button.addTarget(self, action: #selector(back), for: .touchUpInside)
view.addSubview(button)
view.backgroundColor = UIColor.white //设置一下北京色,不然是黑的😂
print("second page")
}
func back() {
// 返回上一页
self.navigationController?.popViewController(animated: true)
}
}

点击Back按钮,返回上一页。使用navigationController下的popViewController方法实现返回。但是如果这时编译页面,在模拟器中点击Next按钮,发现并没有任何事情发生😅这块找了半天才找到解决办法,最后发现,是没有实例化UINavigationController,其实看到navigationController是一个可选类型就可以猜到一二。接下来,该在什么地方实例化这个UINavigationController呢?如果你直接在页面实例化,发现一样不管用。类比一下react里的路由(react-router 4.0之前的版本),就会发现,导航其实是一个全局的东西,来管理所有的界面堆栈,而不是存在于某一个页面内。如果放入某一个页面内,每次加载都是实例化的一个新UINavigationController,它在其他页面是没法被拿到的。如这个例子中,如果在第一页实例化一个导航控制器,在第二页中是拿不到的。所以,要解决这个问题,就要实例化一个全局的UINavigationController。我们可以在AppDelegate.swift中实例化这个全局导航器。在application方法中,添加如下代码:

1
2
3
4
5
6
let mainPage = ViewController()
let navRoot = UINavigationController(rootViewController: mainPage)
window = UIWindow(frame: UIScreen.main.bounds)
window?.backgroundColor = UIColor.white
window?.rootViewController = navRoot

即通过给window的rootViewController赋值一个UINavigationController实例,就可以在所有页面使用navigationController了。这里其实是重写了应用启动后的默认行为,所以需要在实例化UINavigationController时指定一下根试图。同时,把window大小设置成了满屏。然后给个背景色,否则是黑的😓。这样就可以了,其他页面直接使用pushViewControllerpopViewController就可以了。

临时页面的跳转

临时页面跳转,不知道有没有一个专业的名称。我觉得可以看作是一个弹出页,比如点击一个表单控件,可以弹出一个相应的编辑页。这个是属于该页面的行为,所以不需要全局使用,视图自带。代码还是用上面的,不过跳转方法改一下就可以了。跳转到下一页,可以用self.present(anotherView, animated: true, completion: nil),这样页面会从底部弹出。收回页面,调用self.dismiss(animated: true, completion: nil)。这里灰常简单,就认识俩方法而已。

over!