简体   繁体   English

转到 UIViewController 从 SwiftUI 查看

[英]Segue To UIViewController From SwiftUI View

I am working to implement some SwiftUI content into my existing app.我正在努力将一些 SwiftUI 内容实施到我现有的应用程序中。 I currently have a UIViewController, which hosts a MTKView for camera preview.我目前有一个 UIViewController,它托管一个用于相机预览的 MTKView。

I have created a new SwiftUI view, which is now my root view, as set in my SceneDelegate.swift file.我创建了一个新的 SwiftUI 视图,它现在是我的视图,在我的SceneDelegate.swift文件中设置。 The SwiftUI view loads at launch, as expected.正如预期的那样,SwiftUI 在启动时查看加载。 Now, I would like to create a segue in which, when a user taps on a row in my List, it will segue, full-screen to my existing UIViewController. Here is how I'm calling that;现在,我想创建一个 segue,当用户点击我的列表中的一行时,它将全屏显示到我现有的 UIViewController。这就是我的调用方式;

var body: some View {
    VStack {
        NavigationView {
            List(sessionTypes) { session in
                NavigationLink(destination: CameraControllerWrapper()) {
                    SessionRow(session: session)
                    .frame(height: 40.0)
                }
            }
        .navigationBarTitle(Text("Camera Types"))
        }
    }
}

For posterity, here is my CameraControllerWrapper UIViewControllerRepresentable;对于后代,这是我的CameraControllerWrapper UIViewControllerRepresentable;

struct CameraControllerWrapper: UIViewControllerRepresentable {
typealias UIViewControllerType = CameraController

   func makeUIViewController(context: UIViewControllerRepresentableContext<CameraControllerWrapper>) -> CameraControllerWrapper.UIViewControllerType {
    return CameraController()
   }

   func updateUIViewController(_ uiViewController: CameraControllerWrapper.UIViewControllerType, context: UIViewControllerRepresentableContext<CameraControllerWrapper>) {
    //
   }
}

While this "works," my app crashes as soon as the CameraController is called, as it seems any of my IBOutlets cannot be found.虽然这“有效”,但只要调用 CameraController,我的应用程序就会崩溃,因为似乎无法找到我的任何 IBOutlets。 CameraController is a UIViewController built in the storyboard. CameraController是storyboard内置的UIViewController。

I managed to resolve this by realizing that I needed to instantiate the UIViewController from the Storyboard, and not in code (as I had built its layout in Storyboard, alongside some programatic elements).我设法解决了这个问题,意识到我需要从 Storyboard 实例化 UIViewController,而不是在代码中(因为我在 Storyboard 中构建了它的布局,以及一些编程元素)。 To use the above NavigationLink , I needed to adjust my UIViewControllerRepresentable as such;要使用上面的NavigationLink ,我需要像这样调整我的UIViewControllerRepresentable

struct CameraControllerWrapper: UIViewControllerRepresentable {
    typealias UIViewControllerType = CameraController

    func makeUIViewController(context: UIViewControllerRepresentableContext<CameraControllerWrapper>) -> CameraControllerWrapper.UIViewControllerType {

    let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    let mainViewController: CameraController = mainStoryboard.instantiateViewController(withIdentifier: "CameraController") as! CameraController
      return mainViewController

    }

    func updateUIViewController(_ uiViewController: CameraControllerWrapper.UIViewControllerType, context: UIViewControllerRepresentableContext<CameraControllerWrapper>) {
        //
    }
}

A few potential optimizations for @ZbadhabitZ answer, for people who may be relatively new to Swift, starting with a brief example. @ZbadhabitZ 回答的一些潜在优化,对于 Swift 可能相对较新的人,从一个简短的例子开始。

extension NotesVC : UIViewControllerRepresentable {

    func makeUIViewController(context: Context) -> NotesVC {
        let storyboard =  UIStoryboard(name: "Main", bundle: nil)
        let vc = storyboard.instantiateViewController(withIdentifier: "NotesVC") 
        return vc as! NotesVC
    }

    func updateUIViewController(_ vc: NotesVC, context: Context) {
        // your stuff here
    }
}
  1. Consider adding Swift Protocols as extensions.考虑添加 Swift 协议作为扩展。 It can be tidier and more flexible (including being able to adapt a class to a protocol by defining the protocol extension in a separate file entirely).它可以更简洁、更灵活(包括能够通过在单独的文件中完全定义协议扩展来使 class 适应协议)。 For example, I recently tried out a 3rd party tab controller that required adapting my class to a protocol and the instructions entailed editing several files both added and my own and I was able to put 80% of it into a separate file as extensions and didn't have to muck up my code while experimenting with the new stuff, and it was easy to remove when I was done with it.例如,我最近尝试了一个第三方选项卡 controller,它需要将我的 class 调整为一个协议,并且说明需要编辑几个添加的文件和我自己的文件,我能够将其中 80% 的文件作为扩展名放入一个单独的文件中,并且没有在试验新东西时不必弄乱我的代码,并且在我完成后很容易将其删除。

  1. Function arguments with the heavy typing are overkill; Function arguments 重打字太过分了; or confusing, at least.或至少令人困惑。

    Apple Developer demo shows an example with PageViewController that shows all the extra typing isn't necessary: Apple Developer demo展示了一个带有 PageViewController 的示例,显示所有额外的输入都是不必要的:


  1. The original answer's code doesn't make use of Swift implied types.原始答案的代码没有使用 Swift 隐含类型。 For example, rather例如,而

     let flag: Bool = false

    Instead write:而是写:

     let flag = false

    flag will be typed as Bool implicitly in that declaration. flag将在该声明中隐式类型为Bool That is because false always implies Bool .那是因为false总是意味着Bool Just as 1.0 always implies Double by default, and so on.正如默认情况下1.0始终表示Double一样,依此类推。 The payoff gets even bigger when you start getting into longer class names.当您开始使用更长的 class 名称时,收益会更大。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM