随着Swift 5引入了用于创建视图的SwiftUI框架,但是我们目前正在使用情节提要进行UI设计。
所以我只想知道在同一iOS Single View应用程序中使用Storyboard和Swift UI的过程。
答案 0 :(得分:9)
我刚刚开始看SwiftUI
。分享一个小例子。
storyboard
中添加Hosting View Controller
UIHostingController
子类化ChildHostingController
ChildHostingController
应该看起来像这样:
import UIKit
import SwiftUI
struct SecondView: View {
var body: some View {
VStack {
Text("Second View").font(.system(size: 36))
Text("Loaded by SecondView").font(.system(size: 14))
}
}
}
class ChildHostingController: UIHostingController<SecondView> {
required init?(coder: NSCoder) {
super.init(coder: coder,rootView: SecondView());
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
有关更多详细信息,请查看Custom UIHostingController
Apple Docs UIhostingController(很遗憾,尚未记录)
Integrating SwiftUI Video
答案 1 :(得分:3)
是的,您可以这样做!您可以按照以下步骤操作:
转到当前的Xcode项目->情节提要,单击+号(右上角),然后搜索 Hosting Controller (托管按钮)(就像按钮或标签一样)。
将Hosting Controller拖到Storyboard。创建一个从您的UI元素(我正在使用按钮)到该Hosting Controller的Segue连接,然后选择“推送”。 创建从该Segue到View Controller的插座连接(这是一项新功能-就像您为Label创建插座一样),并为其命名。
例如:我在当前项目中创建了一个SwiftUI视图(在Xcode中:File-> New-> File-> SwiftUI View),并将其命名为DetailsView。我的插座连接看起来像这样:
import UIKit
import SwiftUI
class ViewController: UIViewController {
@IBSegueAction func showDetails(_ coder: NSCoder) -> UIViewController? {
let detailsView = DetailsView()
return UIHostingController(coder: coder, rootView: detailsView)
}
override func viewDidLoad() {
super.viewDidLoad()
// some code
}
}
就是这样!现在运行它。
答案 2 :(得分:2)
Edgell提到,有一个名为ViewController
的新HostViewController
可以在其中托管一个SwiftUI
页面。
关于将SwiftUI集成到WWDC的现有项目中的完整讨论可以很好地回答您的问题。
集成SwiftUI: https://developer.apple.com/videos/play/wwdc2019/231/
答案 3 :(得分:1)
您可以在同一项目中同时使用它们。
SwiftUI只是一个框架。您可以使用SwiftUI创建一个VC,并使用情节提要创建另一个VC。选择是您的。
只需将SwiftUI导入到要使用的地方
答案 4 :(得分:1)
您需要在情节提要中添加“主机视图控制器”。 SwiftUI表单将显示在Host View Controller中,并且可以从任何Storyboard表单中调用。
请注意,Host View Controller不在Mohave的Xcode 11库中显示,您必须在Catalina上。这是一个错误,因为一旦您在Catalina上创建了一个包含Host View Controller的项目,该项目就可以在Mohave上正常运行,实际上,您甚至可以将该Host View Controller复制到其他Storyboard,并且可以正常运行。 / p>
答案 5 :(得分:1)
将 UIKit 与 SwiftUI 混合
两者都可以在 Storyboards 中嵌入和混合 SwiftUI,反之亦然
UIViewControllerRepresentable 用于在 SwiftUI 中嵌入 Storyboard
在 Storyboard 上创建 ViewController 并给它一个 Storyboard ID
import SwiftUI
struct ContentView: View {
var body: some View {
StoryboardViewController()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct StoryboardViewController: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> some UIViewController {
let storyboard = UIStoryboard(name: "Storyboard", bundle: Bundle.main)
let controller = storyboard.instantiateViewController(identifier: "Main")
return controller
}
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
}
}
UIKit 和 SwiftUI 之间的通信可以通过 @Binding 变量进行。这将让 SwiftUI 视图注入变量状态并控制它,func updateUIViewController 将在更改时被调用来完成工作。
UIViewRepresentable 对视图使用相同的方式
import SwiftUI
struct ContentView: View {
@State var color = UIColor.green
var body: some View {
SampleView(color: $color).frame(width: 100, height: 100
, alignment: .center)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct SampleView: UIViewRepresentable {
@Binding var color: UIColor
func makeUIView(context: Context) -> some UIView {
return UIView()
}
func updateUIView(_ uiView: UIViewType, context: Context) {
uiView.backgroundColor = color
}
}
UIHostingController 用于在 UIKit 中嵌入 SwiftUI
Fisrt 以编程方式创建
let childViewController = UIHostingController(rootView: SwiftUIContentView())
addChild(childViewController)
childViewController.view.frame = frame
view.addSubview(childViewController.view)
childViewController.didMove(toParent: self)
第二 使用 Xcode 11,通过将托管视图控制器添加到情节提要并为其创建一个转场,然后通过 Control-drag 从转场到您的 ViewController 创建一个 @IBSegueAction,然后创建一个实例SwiftUI 视图并将其传递给 HostingViewController 初始值设定项
第三是通过将托管视图控制器添加到情节提要中,然后按照上述https://stackoverflow.com/a/58250271/3033056