从 UIViewControllerRepresentable 对象访问 @Environment 对象 [英] Access @Environment object from UIViewControllerRepresentable object

查看:70
本文介绍了从 UIViewControllerRepresentable 对象访问 @Environment 对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

<块引用>

致命错误:找不到数据类型的 ObservableObject.一种View.environmentObject(_:) for Data 可能缺少作为此视图

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

导入 UIKit导入 SwiftUI进口结合最终类 PageFourView: UIViewController, UIViewControllerRepresentable {公共类型别名 UIViewControllerType = PageFourView@EnvironmentObject var 数据:数据var previewView: UIView!覆盖 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.scaleAspectFitview.addSubview(previewView)}func makeUIViewController(context: UIViewControllerRepresentableContext) ->PageFourView {打印(上下文.环境)打印(self.data.Name)返回 PageFourView()}func updateUIViewController(_ uiViewController: PageFourView, context: UIViewControllerRepresentableContext) {}}struct PageFourView_Previews: PreviewProvider {@State 静态 var 数据 = Data()静态 var 预览:一些视图 {PageFourView().environmentObject(self.data)}}

这是调用 PageFourView 的父视图:

<预><代码>导入 SwiftUIstruct AppView:查看{@EnvironmentObject var 数据:数据var主体:一些视图{标签视图{PageOneView().environmentObject(data).tabItem {文本(PageOne")}PageTwoView().environmentObject(data).tabItem {文本(第二页")}PageThreeView().environmentObject(data).tabItem {文本(第三页")}PageFourView().environmentObject(data).tabItem {文本(第四页")}}}}struct AppView_Previews: PreviewProvider {@State 静态 var 数据 = Data()静态 var 预览:一些视图 {AppView().environmentObject(self.data)}}

final class CameraViewController: UIViewController {让 cameraController = CameraController()var previewView: UIView!覆盖 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.scaleAspectFitview.addSubview(previewView)cameraController.prepare {(error) in如果让错误 = 错误 {打印(错误)}尝试?self.cameraController.displayPreview(on: self.previewView)}}}扩展 CameraViewController : UIViewControllerRepresentable{公共类型别名 UIViewControllerType = CameraViewControllerpublic func makeUIViewController(context: UIViewControllerRepresentableContext) ->相机视图控制器 {返回 CameraViewController()}public func updateUIViewController(_ uiViewController: CameraViewController, context: UIViewControllerRepresentableContext) {}}

解决方案

And UIViewRepresentable and UIViewControllerRepresentable is-a View and 必须是结构体.

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

struct PageFourView: UIViewRepresentable {@EnvironmentObject var 数据:数据func makeUIView(context: Context) ->界面视图{让视图 = UIView(frame: CGRect(x:0, y:0, width: UIScreen.main.bounds.size.width,高度:UIScreen.main.bounds.size.height))view.contentMode = UIView.ContentMode.scaleAspectFit打印(上下文.环境)打印(self.data.Name)返回视图}func updateUIView(_ uiView: UIView, context: Context) {}}

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

var body: some View {标签视图{PageOneView().tabItem {文本(PageOne")}PageTwoView().tabItem {文本(第二页")}PageThreeView().tabItem {文本(第三页")}PageFourView().tabItem {文本(第四页")}}}

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

struct CameraView: UIViewControllerRepresentable {func makeUIViewController(context: Context) ->相机视图控制器 {相机视图控制器()}func updateUIViewController(_ uiViewController: CameraViewController, context: Context) {}}

I used this approach to incorporate camera with swiftUI: https://medium.com/@gaspard.rosay/create-a-camera-app-with-swiftui-60876fcb9118

The UIViewControllerRepresentable is implemented by PageFourView class. PageFourView is one of the TabView of the parental View. I have an @EnvironmentObject passed from the SceneDelegate to the parent view and then to PageFourView. But when I am trying to acess @EnvironmentObject from makeUIViewController method of PageFourView I get an error:

Fatal error: No ObservableObject of type Data found. A View.environmentObject(_:) for Data may be missing as an ancestor of this view

... even though I can see the @Environment object from context.environment. Here is my code:

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)
    }
}

here is the parental view that PageFourView is called from:


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>) {
    }
}

解决方案

And UIViewRepresentable and UIViewControllerRepresentable is-a View and must be a struct.

In described case controller representable is not needed, because you operate with view, so here is corrected code:

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) {
    }
}

btw, you don't need to pass .environmentObject to subviews in same view hierarchy, only for new hierarchy, like sheets, so you can use simplified code as below

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

Update: for CameraViewController just wrap it as below

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

    func updateUIViewController(_ uiViewController: CameraViewController, context: Context) {
    }
}

这篇关于从 UIViewControllerRepresentable 对象访问 @Environment 对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆