有没有办法在同一个iOS Xcode项目中使用Storyboard和SwiftUI?

时间:2019-06-10 15:40:21

标签: xcode storyboard swiftui

随着Swift 5引入了用于创建视图的SwiftUI框架,但是我们目前正在使用情节提要进行UI设计。

所以我只想知道在同一iOS Single View应用程序中使用Storyboard和Swift UI的过程。

6 个答案:

答案 0 :(得分:9)

我刚刚开始看SwiftUI。分享一个小例子。

  1. storyboard中添加Hosting View Controller
  2. 用您自己的课程(UIHostingController子类化ChildHostingController enter image description here
  3. 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)

是的,您可以这样做!您可以按照以下步骤操作:

  1. 转到当前的Xcode项目->情节提要,单击+号(右上角),然后搜索 Hosting Controller (托管按钮)(就像按钮或标签一样)。

  2. 将Hosting Controller拖到Storyboard。创建一个从您的UI元素(我正在使用按钮)到该Hosting Controller的Segue连接,然后选择“推送”。 创建从该Segue到View Controller的插座连接(这是一项新功能-就像您为Label创建插座一样),并为其命名。

enter image description here

  1. 在此插座连接中声明您的视图(可以执行此操作,不必使用PrepareForSegue方法),然后将其返回。

例如:我在当前项目中创建了一个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/

WWDC19: https://developer.apple.com/videos/

答案 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