SwiftUI中的非View子类是否可以访问environmentObject

时间:2020-04-18 15:43:59

标签: swift swiftui

我了解到EnvironmentObjects用于在视图之间共享数据。 我很想知道其他非View子类是否可以访问EnvironmentObjects并更新它们。 如果是,我们在这里打破任何建筑模式吗?
如果需要访问非View子类中的EnvironmentObjects,应该采取什么方法

Edit-I

我正在使用AVFoundation来获取视频帧。收到框架后,我尝试更新一个environmentObject,以便所有视图都可以访问该框架。下面是代码:

class Coordinator {

    let delegate = VideoDelegate()
    let controller: CameraController!

    init(){

        controller = CameraController(delegate)
    }
}

final class VideoDelegate: NSObject, AVCaptureVideoDataOutputSampleBufferDelegate{
    @EnvironmentObject var frame: CIImageFrame

    func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {

        if let cvImageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) {

            self.frame.image = CIImage(cvImageBuffer: cvImageBuffer)

        } else {

            //Log message
            print("CMSampleBuffer to CIImage conversion error")
        }
    }
}



//Wrap CIImage to make it EnvironmentObject
final class CIImageFrame: ObservableObject {
   @Published var image = CIImage()
}

在其中一个视图中创建了Coordinator对象

1 个答案:

答案 0 :(得分:1)

EnvironmentObject只是一种将确认ObservableObject协议的引用类型的实例注入SwiftUI视图层次结构中并在相应属性发生更改时更新此类视图的机制,只需观察相应的发布者即可。但这只是普通的引用类型实例,您可以以与传递其他任何引用类型实例相同的方式在这里和那里传递它,并与其他引用类型实例一样使用它(属性,函数)进行操作。

没有魔术。

更新:立即进行编码

您不需要在委托中使用@EnvironmentObject包装器,而是用于视图,而是使用以下包装(从头开始,作为代码剪切)

class Coordinator {
    let owner: _Owner_Type_     // << here is owner view of coordinator
    let delegate: VideoDelegate
    let controller: CameraController!

    init(owner: _Owner_Type_){
        self.owner = owner

        // owner is view which has @EnvironmentObject property, 
        // so use it here to pass into VideoDelegate
        delegate = VideoDelegate(frame: owner.frame)

        controller = CameraController(delegate)
    }
}

final class VideoDelegate: NSObject, AVCaptureVideoDataOutputSampleBufferDelegate{
    private var frame: CIImageFrame // just reference member

    // now your delegate has reference to the same instance as environment
    // object in view
    init(frame: CIImageFrame) {
       self.frame = frame
    }
    ...

相关问题