SwiftUI 與 Storyboard 混合使用研究
發表於|更新於
前言
最近需要支援同事開發iOS APP,同事主要用Storyboard開發,自己則想用主流技術SwiftUI開發,因此需要將兩者混合使用,這邊紀錄一下研究過程。
為何想使用SwiftUI,主要使用過Android Jetpack Compose經驗,覺得Jetpack Compose的開發體驗非常好,因此想嘗試SwiftUI。
SwiftUI主要能提供的優點為:
- 元件佈局異動不用再重新調整約束。
- ViewController.swift檔名異動時,不用再手動調整Storyboard Scene對應。
- 實作的局部元件,可容易讓其他頁面重覆使用。
- 可享受MVVM好處。
經過溝通會以功能模組進行切割,因此只要針對功能模組UI實作、API串接後,後續提供參數給同事進行呼叫即可。
下載原始碼
原始碼下載
專案快速啟動指令
kevin_swiftui_storyboard_mixed_use__xcode
[多種開發語言專案管理工具]
驗證項目
- Storyboard嵌入SwiftUI(這次專案需求)
- Xib嵌入SwiftUI
- Storyboard啟動SwiftUI ViewController
待驗證項目
- SwiftUI 嵌入 Storyboard
- SwiftUI 嵌入 Xib
驗證過程
專案結構
建立一個Storyboard專案,並在Main.storyboard的Main View Controller Scene
新增三個按鈕,分別為Show StoryboardViewController
、Show XibViewController
與Show SwiftUIViewController
。
這三個按鈕動作分別為:
Show StoryboardViewController
啟動 Storyboard View Controller Scene
。
Show XibViewController
啟動 XibViewController.swift
。
Show SwiftUIViewController
啟動 SwiftUIViewController.swift
。
透過UIHostingController元件將SwiftUI View嵌入到ViewController view中。
原始碼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
import UIKit import SwiftUI
class MainViewController: UIViewController {
@IBAction func clickShowXibViewController(_ sender: Any) { XibViewController.show(self) } @IBAction func clickShowSwiftUIViewcontroller(_ sender: Any) { SwiftUIViewController.show(self) } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
import UIKit import SwiftUI
class StoryboardViewController: UIViewController {
static func show(_ parent:UIViewController){ parent.show(Self(), sender: parent ) } override func viewDidLoad() { super.viewDidLoad() let childView = UIHostingController(rootView: SwiftUISubView()) addChild(childView) childView.view.frame = CGRect(x: 0, y: UIScreen.main.bounds.height*0.6, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height*0.3) self.view .addSubview(childView.view) childView.didMove(toParent: self) }
@IBAction func clickClose(_ sender: Any) { self.dismiss(animated: true,completion: nil) } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
|
import UIKit import SwiftUI
class XibViewController: UIViewController { static func show(_ parent:UIViewController){ parent.show(Self(), sender: parent ) }
override func viewDidLoad() { super.viewDidLoad() let childView = UIHostingController(rootView: SwiftUISubView()) addChild(childView) childView.view.frame = CGRect(x: 0, y:UIScreen.main.bounds.height*0.6, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height*0.3) self.view .addSubview(childView.view) childView.didMove(toParent: self) }
@IBAction func clickClose(_ sender: Any) { self.dismiss(animated: true,completion: nil) } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
import SwiftUI
struct SwiftUISubView: View { var body: some View { Color.blue .overlay( VStack(spacing: 20) { Text("SwiftUISubView").font(.largeTitle) }) } }
struct SwiftUISubView_Previews: PreviewProvider { static var previews: some View { SwiftUISubView() } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
|
import UIKit import SwiftUI
class SwiftUIViewController: UIViewController { static func show(_ parent:UIViewController){ parent.show(Self(), sender: parent ) }
override func viewDidLoad() { let childView = UIHostingController(rootView: SwiftUIView()) addChild(childView) childView.view.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height) self.view .addSubview(childView.view) childView.didMove(toParent: self) }
struct SwiftUIView: View { @Environment(\.presentationMode) var presentationMode var body: some View { Color.red .overlay( VStack(spacing: 20) { Text("SwiftUIViewController").font(.largeTitle) Button(action: { presentationMode.wrappedValue.dismiss() }) { Text("Close") } }) } }
struct SwiftUIView_Previews: PreviewProvider { static var previews: some View { SwiftUIView() } } }
|
執行結果
Keyword
1 2 3
| 驗證, Validation, val-ida-tion 場景, Scene, sc-ene 故事板, Storyboard, story-board
|