3

我使用这种方法将相机与 swiftUI 结合起来: https ://medium.com/@gaspard.rosay/create-a-camera-app-with-swiftui-60876fcb9118

UIViewControllerRepresentable 由 PageFourView 类实现。PageFourView 是父 View 的 TabView 之一。我@EnvironmentObject从 SceneDelegate 传递到父视图,然后传递到 PageFourView。但是当我试图@EnvironmentObject从 PageFourView 的 makeUIViewController 方法访问时,我得到一个错误:

致命错误:未找到数据类型的 ObservableObject。Data 的 View.environmentObject(_:) 作为此视图的祖先可能会丢失

...即使我可以从 context.environment 中看到 @Environment 对象。这是我的代码:

import UIKit
import SwiftUI
import Combine


final class PageFourView: UIViewController, UIViewControllerRepresentable {
    
    public typealias UIViewControllerType = PageFourView
    
    @EnvironmentObject var data: Data
    
    var previewView: UIView!
    
    override func viewDidLoad() {
        
        previewView = UIView(frame: CGRect(x:0, y:0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height))
        
        previewView.contentMode = UIView.ContentMode.scaleAspectFit
        view.addSubview(previewView)
        
    }
    
    func makeUIViewController(context: UIViewControllerRepresentableContext<PageFourView>) -> PageFourView {
        print(context.environment)
        print(self.data.Name)
        return PageFourView()
    }

    func updateUIViewController(_ uiViewController: PageFourView, context: UIViewControllerRepresentableContext<PageFourView>) {
    }
}

struct PageFourView_Previews: PreviewProvider {
    @State static var data = Data()
    static var previews: some View {
        PageFourView().environmentObject(self.data)
    }
}

这是从中调用 PageFourView 的父视图:


import SwiftUI

struct AppView: View {
    
    @EnvironmentObject var data: Data
    
    var body: some View {
        TabView {
            PageOneView().environmentObject(data)
                .tabItem {
                    Text("PageOne")
                }

            PageTwoView().environmentObject(data)
                .tabItem {
                    Text("PageTwo")
                }
            PageThreeView().environmentObject(data)
            .tabItem {
                Text("PageThree")
            }
            PageFourView().environmentObject(data)
            .tabItem {
                Text("PageFour")
            }
            
            
        }
    }
}

struct AppView_Previews: PreviewProvider {
    
    @State static var data = Data()
    static var previews: some View {
        AppView().environmentObject(self.data)
    }
}
final class CameraViewController: UIViewController {
    let cameraController = CameraController()
    var previewView: UIView!

    override func viewDidLoad() {

        previewView = UIView(frame: CGRect(x:0, y:0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height))
        previewView.contentMode = UIView.ContentMode.scaleAspectFit
        view.addSubview(previewView)

        cameraController.prepare {(error) in
            if let error = error {
                print(error)
            }

            try? self.cameraController.displayPreview(on: self.previewView)
        }

    }
}


extension CameraViewController : UIViewControllerRepresentable{
    public typealias UIViewControllerType = CameraViewController

    public func makeUIViewController(context: UIViewControllerRepresentableContext<CameraViewController>) -> CameraViewController {
        return CameraViewController()
    }

    public func updateUIViewController(_ uiViewController: CameraViewController, context: UIViewControllerRepresentableContext<CameraViewController>) {
    }
}
4

1 回答 1

3

And UIViewRepresentableand UIViewControllerRepresentableis-a Viewand must be a struct

在所描述的情况下不需要控制器表示,因为您使用视图进行操作,所以这里是更正的代码:

struct PageFourView: UIViewRepresentable {
    @EnvironmentObject var data: Data

    func makeUIView(context: Context) -> UIView {
        let view = UIView(frame: CGRect(x:0, y:0, width: UIScreen.main.bounds.size.width, 
                          height: UIScreen.main.bounds.size.height))
        view.contentMode = UIView.ContentMode.scaleAspectFit

        print(context.environment)
        print(self.data.Name)
        return view
    }

    func updateUIView(_ uiView: UIView, context: Context) {
    }
}

顺便说一句,您不需要传递.environmentObject给同一视图层次结构中的子视图,仅适用于新层次结构,如工作表,因此您可以使用如下简化代码

var body: some View {
    TabView {
        PageOneView()
            .tabItem {
                Text("PageOne")
            }
        PageTwoView()
            .tabItem {
                Text("PageTwo")
            }
        PageThreeView()
        .tabItem {
            Text("PageThree")
        }
        PageFourView()
        .tabItem {
            Text("PageFour")
        }
    }
}

更新:只需CameraViewController将其包装如下

struct CameraView: UIViewControllerRepresentable {
    func makeUIViewController(context: Context) -> CameraViewController {
        CameraViewController()
    }

    func updateUIViewController(_ uiViewController: CameraViewController, context: Context) {
    }
}
于 2020-07-10T03:28:32.460 回答