Доступ к объекту @Environment из объекта UIViewControllerRepresentable
Я использовал этот подход для включения камеры в swiftUI:https://medium.com/@gaspard.rosay/create-a-camera-app-with-swiftui-60876fcb9118
UIViewControllerRepresentable реализуется классом PageFourView. PageFourView является одним из TabView родительского View. у меня есть@EnvironmentObject
передается из SceneDelegate в родительское представление, а затем в PageFourView. Но когда я пытаюсь получить доступ@EnvironmentObject
из метода makeUIViewController PageFourView я получаю сообщение об ошибке:
Неустранимая ошибка: не найдено ObservableObject типа Data. View.environmentObject(_:) для данных может отсутствовать как предок этого представления
... хотя я вижу объект @Environment из context.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>) {
}
}
1 ответ
А также UIViewRepresentable
а также UIViewControllerRepresentable
это View
и должен быть структурой.
В описанном случае представление контроллера не требуется, потому что вы работаете с представлением, поэтому вот исправленный код:
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) {
}
}