【问题标题】:How to update encapsulating SwiftUI View from MKMapView didSelect annotation如何从 MKMapView didSelect 注释更新封装的 SwiftUI 视图
【发布时间】:2020-10-18 22:37:32
【问题描述】:

从 MKMapKit didSelect 注解委托中向封装的 SwiftUI 视图推送更新的适当方法是什么?

struct CompoundView: View {
  @State private var selected: MKAnnotation?
  
  var body: some View {
    ZStack {
      MapView(annotations: annotations, selected: $selected)
      if let selected = selected {
        PopUpView(selected)
      }
    }
  }
}

MapView 被实现为带有代表的UIViewRepresentable

func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
  subject.selected = view.annotation // subject is the controller's reference to the MapView wrapping MKMapView 
}

将回调传递给更新 CompoundView 状态的委托会导致 XCode 触发 Modifying state during view update, this will cause undefined behavior. 它还可以防止 MKMapView 中的注释引脚被明显选择(引脚图标在第一次不会增长被点击)。

同样,将绑定从CompoundView 传递到MapView 似乎是有问题的,因为点击时图钉图标不增长的问题仍然存在。我假设由于状态更改而重建父视图。

我尝试将委托逻辑包装在 DispatchQueue.main.async 调用中,但没有成功,此时我只是在猜测。

是否有一种首选方法可以从 MKMapView 委托调用中将信息反馈给父视图,这样我们既不在视图更新中,也不会阻止地图注释在点击时正常动画?

【问题讨论】:

    标签: ios swiftui mapkit


    【解决方案1】:

    编辑:事实证明,我在选择时没有动画的注释问题的根源在于,每当视图更新时,我都会不断刷新注释。在makeUIView 中添加注释并将updateUIView 留空解决了很多奇怪的交互。

    func updateUIView(_ map: MKMapView, context: Context) {
      map.removeAnnotations(map.annotations)
      map.addAnnotations(annotations)
    }
    

    通过使用ObservableObject,我能够让两个视图都发挥得很好。该对象将@Published 父视图订阅的选定注释@ObservedObject(或@StateObject)。然后地图视图从委托调用中更新了可观察对象的注释类成员。请注意,地图视图不会将对象标记为@ObservedObject,因为当模型发生更改时地图视图不应更新(这会导致地图注释出现错误并且在选择和取消选择时没有动画)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-28
      • 1970-01-01
      • 1970-01-01
      • 2014-05-18
      • 2012-10-12
      • 1970-01-01
      相关资源
      最近更新 更多