本文基于 Xcode 12.3 Swfit 5.3.2 iOS 14.3 macOS 11.2 构建
无意间发现好像不止可以在 Swift UI 中用上 UIKit,反过来亦然。
首先打开 Xcode 新建一个 Cocoa Touch 项目,interface 选择 Storyboard。
随后,新建一个 Swift UI File,命名为 ContentView.swift。文件会自动生成一个 ContentView 的 Swift UI View。
接下来需要把 Swift UI View 用在 UIKit 中,需要用到 Swift UI 中的
UIHostingController
。这是可以把 Swift UI 包装成 UIView。
在 Main.stroyboard 中将 rootViewController 包装上一个 NavigtaionController,不用多说了。之后打开 ViewController.swift。在 viewDidLoad 中加上如下代码:
swift
代码语言:javascript复制1let uiButton = UIButton(type: .system)
2
3uiButton.setTitle("Button", for: .normal)
4uiButton.translatesAutoresizingMaskIntoConstraints = false
5uiButton.addTarget(self, action: #selector(click), for: .touchUpInside)
6
7view.addSubview(uiButton)
8
9uiButton.snp.makeConstraints { make in
10 make.center.equalTo(view)
11}
COPY
方便起见,以上代码使用了 SnapKit,在运行之前请先下载安装
SnapKit
在再底下加个方法
swift
代码语言:javascript复制1@objc func click() {
2 let vc = UIHostingController(rootView: ContentView())
3
4 navigationController?.pushViewController(vc, animated: true)
5}
COPY
OK, 现在可以 Run 了。点击中央的 Button 之后将会 Push 到一个由 Swift UI 构建的 View。
接下来,如果不用 PushViewController 的方式把 Swift UI View 直接挂载到 RootViewController。
将 ViewController 中 viewDidLoad
中代码替换成
swift
代码语言:javascript复制1super.viewDidLoad()
2let hostVc = UIHostingController(rootView: ContentView())
3view.backgroundColor = .systemBackground
4let sview = hostVc.view as! UIView
5
6view.addSubview(sview)
7sview.snp.makeConstraints({ make in
8 make.bottom.equalTo(view)
9 make.top.equalTo(view)
10 make.left.equalTo(view)
11 make.right.equalTo(view)
12 make.width.equalTo(view)
13 make.height.equalTo(view)
14})
COPY
然后我又发现了点好玩的东西。如何在 Swift UI 直接用上 UINavigationController 和 UITabBarController。
Innei/SwiftUI-in-UIKit-with-UINavtigationController-test
https://twitter.com/__oquery/status/1358376605995868162?s=21
刺激。
NavigationController 外置的另一方式
如下写法能让 SwiftUI 内部识别到外层 UINavigationController,无需包裹 NavigationView 即可使用 NavigationLink,同时还能使用 UINavigationController 更完善的方法。
swift
代码语言:javascript复制1var hv = UIHostingController(rootView: TestView())
2var myNavigationController = UINavigationController(rootViewController: hv)
3
4struct TestView: View {
5 var body: some View {
6 Form {
7 NavigationLink("Navigation", destination: EmptyView())
8 }.navigationTitle("Test")
9 }
10}
11
12class ViewController: UIViewController {
13 override func viewDidLoad() {
14 super.viewDidLoad()
15 }
16}
17