47

由于 Swift 5 引入了用于创建视图的 SwiftUI 框架,但我们目前正在使用故事板进行 UI 设计。

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

4

5 回答 5

53

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

  1. storyboard添加Hosting View Controller
  2. UIHostingController用您自己的类 ( ChildHostingController) 子类化在此处输入图像描述
  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()
    }
}

有关更多详细信息,请查看自定义 UIHostingController
Apple Docs UIhostingController(不幸的是尚未记录)
集成 SwiftUI 视频

于 2019-10-05T16:31:58.487 回答
8

将 UIKit 与 SwiftUI 混合使用

两者都可以在 Storyboard 中嵌入和混合 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

首先是以编程方式创建

let childViewController = UIHostingController(rootView: SwiftUIContentView())
addChild(childViewController)
childViewController.view.frame = frame
view.addSubview(childViewController.view)
childViewController.didMove(toParent: self)

其次是 Xcode 11,通过将 Hosting View Controller 添加到情节提要并为其创建一个 segue,然后通过 Control-drag 从 segue 到您的 ViewController 创建一个 @IBSegueAction,然后创建 SwiftUI 视图的实例并将其传递给 HostingViewController 初始化程序

第三是通过将 Hosting View Controller 添加到情节提要中,然后将其子类化,如上面的上一个答案中所述https://stackoverflow.com/a/58250271/3033056

于 2021-03-13T02:24:01.417 回答
7

是的,你可以这么做!以下是您可以采取的步骤:

  1. 转到您当前的 Xcode 项目 -> Storyboard,单击 + 号(右上角)并搜索Hosting Controller(就像您搜索按钮或标签一样)。

  2. 将 Hosting Controller 拖到 Storyboard 中。创建从您的 UI 元素(我正在使用按钮)到该 Hosting Controller 的 Segue 连接,然后选择 Push。创建从 Segue 到您的视图控制器的出口连接(这是一个新功能 - 就像您为标签创建出口一样),并命名它。

在此处输入图像描述

  1. 在这个出口连接中声明你的视图(你可以这样做,不必使用 PrepareForSegue 方法),然后返回它。

例如:我在当前项目中创建了一个 SwiftUI 视图(在 Xcode 中:文件 -> 新建 -> 文件 -> SwiftUI 视图)并将其命名为 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

    }
}

而已!现在运行它。

于 2020-03-19T22:58:00.030 回答
4

正如 Edgell 所提到的,有一个新的ViewController名称HostViewController可以SwiftUI在其中托管一个页面。在 WWDC 上有一个关于将 SwiftUI 集成到现有项目中的完整讨论,它很好地回答了你的问题。

集成 SwiftUI: https ://developer.apple.com/videos/play/wwdc2019/231/

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

于 2019-09-09T08:57:41.323 回答
2

您需要将“主机视图控制器”添加到情节提要。SwiftUI 表单将显示在主机视图控制器中,并且可以从任何 Storyboard 表单中调用。

请注意,主机视图控制器不会显示在 Mohave 上 Xcode 11 的库中,您必须在 Catalina 上。这是一个错误,因为一旦您在 Catalina 上创建了一个带有 Host View Controller 的项目,同一个项目将在 Mohave 上运行良好,事实上,您甚至可以将该 Host View Controller 复制到其他 Storyboard 上,它会正常工作。

于 2019-06-15T03:20:23.957 回答