【问题标题】:SwiftUI and UIKit Interoperability with displaying multiple views显示多个视图的 SwiftUI 和 UIKit 互操作性
【发布时间】:2022-02-04 09:24:51
【问题描述】:

概述:我正在使用 SwiftUI,但想使用 UIKit-MapKit。我使用 UIViewRepresentable 来包装 UIKit 功能。

问题:我正在学习 swiftui-uikit-interoperability,但无法显示多个 SwiftUI 视图。

代码片段:

内容视图

    struct ContentView: View {
    
    @ObservedObject var viewModel: MapView.PinViewModel
    
    init() {
        self.viewModel = MapView.PinViewModel()
    }
    
    var body: some View {
        NavigationView {
            MapView()

            .sheet(isPresented: $viewModel.showPinForm) {
                PinForm()
            }
            
            .navigationTitle("SwiftUI UIKit Interop").scaledToFill()
        }
    }
}

地图视图

struct MapView: UIViewRepresentable {

    class PinViewModel: ObservableObject {
        @Published var showPinForm: Bool
        
        init() {
            self.showPinForm = false
        }

        func updateShowPinVar() {
            self.showPinForm = true
        }
    }

    func showPinForm() {
        pinViewModel.updateShowPinVar()
    }

    func makeCoordinator() -> MapViewCoordinator {
        let coordinator = MapViewCoordinator()
        coordinator.delegate = self
        return coordinator
    }
    
    func makeUIView(context: Context) -> MKMapView {
        let mapView = MKMapView()
        mapView.delegate = context.coordinator
        let coordinate = CLLocationCoordinate2D(latitude: 40.7209, longitude: -74.0007)
        let span = MKCoordinateSpan(latitudeDelta: 0.03, longitudeDelta: 0.03)
        let mapRegion = MKCoordinateRegion(center: coordinate, span: span)
        mapView.setRegion(mapRegion, animated: true)
        return mapView
    }
    
    func updateUIView(_ uiView: MKMapView, context: Context) {
    }
}

在此我有一个在 MapView 中切换的 @Published var showPinForm。 ContentView 应该监视这个变量,当它为真时,它将导致工作表拉起。但是,我相信当我从 ContentView() 进入 MapView() 时,我不再识别 ContentView。

使用 UIViewRepresentable,显示另一个 swiftui 视图的最佳方式是什么?不必使用 .sheet (虽然会很好)

  • 我试图简化代码以显示主要问题,所以我遗漏了很多附加信息并取出了我使用的基本模式 (MVVM) 如果您需要任何说明,请告诉我

【问题讨论】:

  • 你不能为 View 实现ObservableObject,它是为 ViewModel 实现的。为您的 MapView 添加回调或绑定
  • @QuangHà 我删掉了一段重要的代码,但现在已经更新了。我实际上并没有在视图中观察到对象。我在课堂上有它。
  • 如何在MapView 中创建pinViewModel 以及在哪里调用showPinForm?实际上,您需要在 ContentViewMapView 中使用相同的视图模型实例才能在它们之间进行通信。
  • 我们在 SwiftUI 中不使用 MVVM,我们使用 View 结构体来处理视图数据,并使用 @State 和 @Binding 之类的属性包装器来使我们的结构体表现得像对象。最好在处理互操作性之前先了解这一点。
  • @Asperi 我没有在 ContentView 和 MapView 中使用相同的 viewModel 实例。我进行了这些更改并修复了它。简单的忽略,但感谢您的帮助!

标签: swiftui uikit mapkit uiviewrepresentable observedobject


【解决方案1】:

尝试遵循这种模式,您可以在 MapView 内部和外部切换标志

struct MapView: UIViewRepresentable {
    @Binding var switcher: Bool // -> use binding
    func makeUIView(context: Context) -> MKMapView { MKMapView() }
    func updateUIView(_ uiView: MKMapView, context: Context) { }
}
struct MainView: View {
    @ObservedObject var viewModel = MainViewModel()
    var body: some View {
        MapView(switcher: $viewModel.flag)
            .sheet(isPresented: $viewModel.flag) {
                Text("Pin pin")
            }
    }
}
class MainViewModel: ObservableObject {
    @Published var flag: Bool = false
}

【讨论】:

  • 当我像这样实现它时,我在 MapView(ditto: ditto, switcher: $viewModel.flag) 线上得到一个错误,错误说“无法将 'Binding' 类型的值转换为预期参数类型 'Bool'”,因为 flag 是 bool 而 switcher 是绑定
猜你喜欢
  • 2022-11-07
  • 1970-01-01
  • 2023-01-05
  • 2022-07-11
  • 2020-10-19
  • 2021-05-02
  • 2023-04-03
  • 2021-09-06
相关资源
最近更新 更多