【问题标题】:UIViewRepresentable.updateUIView(_:context:) is not called when @State, @Binding or @EnvironmentObject are changedUIViewRepresentable.updateUIView(_:context:) 在@State、@Binding 或@EnvironmentObject 改变时不会被调用
【发布时间】:2020-02-16 20:08:51
【问题描述】:

当此视图及其父视图所依赖的 ObservableObject 发生更改时,不会调用 UIViewRepresentable.updateUIView。

我有一个带有“@State var locationManager: LocationManager”的 GameView,它作为绑定传递给我的 MapView。 MapView 符合 UIViewRepresentable 协议。 LocationManager 除其他外符合 ObservableObject 并具有以下与一致性相关的代码:

var didChange = PassthroughSubject<locationmanager, Never>()  


    var lastKnownLocation: CLLocation {  
        didSet {  

            // Propagate the update to the observers.  
            didChange.send(self)  
            print("Finished propagating lastKnownLocation to the observers.")  
        }  
}

我认为每次 LocationManager.lastKnownLocation 更改时,必须更新 GameView 和 MapView。在实践中,当我按主页按钮退出应用程序时,我只会看到 MapView.updateUIView() 被调用。此时控制进入 updateUIView() 并且当我再次打开应用程序(不是编译安装运行)时,我得到了更新。这也会在 GameView() 出现后不久发生。

我对 SwiftUI 工作原理的理解是错误的还是一些错误?我怎样才能做到正确?

struct GameView: View { 
    @State var locationManager: LocationManager 


    var body: some View { 
        MapView(locationManager: $locationManager)
    }
}

struct MapView: UIViewRepresentable {

    @Binding var locationManager: LocationManager

   func makeUIView(context: Context) -> GMSMapView{ ... }

   func updateUIView(_ mapView: GMSMapView, context: Context) { ... }

}

class LocationManager: NSObject, CLLocationManagerDelegate, ObservableObject {

    var didChange = PassthroughSubject<LocationManager, Never>()

    var lastKnownLocation: CLLocation {
        didSet {


            // Propagate the update to the observers.
            didChange.send(self)
            print("Finished propagating lastKnownLocation to the observers.")
        }
    }

    ...

}

我希望每次 LocationManager.lastKnownLocation 发生变化,都会调用 MapView.updateUIView()。实际上,只有当我按主页按钮退出应用程序(然后再次进入)时才会发生呼叫

【问题讨论】:

    标签: ios swift state swiftui uiviewrepresentable


    【解决方案1】:

    像这样改变 MapView

    struct MapView: UIViewRepresentable {
      @State var locationManager = LocationManager()
    
      func makeUIView(context: Context) -> GMSMapView{
        let view = GMSMapView(frame: .zero)
        ...
        willAppear(context)
        return view
      }
    
      func updateUIView(_ mapView: GMSMapView, context: Context) { ... }
    
      func makeCoordinator() -> MapView.Coordinator {
        return Coordinator()
      }
    
      static func dismantleUIView(_ uiView: GMSMapView, coordinator: MapView.Coordinator) {
        coordinator.cancellable.removeAll()
      }
    
      class Coordinator {
        var cancellable = Set<AnyCancellable>()
      }
    }
    
    extension MapView {
      func willAppear(_ context: Context) {
        locationManager.didChange.sink{
          print("location: \($0)")
        }.store(in: &context.coordinator.cancellable)
    
        locationManager.startUpdating()
      }
    }
    

    我认为locationManager.startUpdating(),locationManager.stopUpdating()这个方法需要调用另一个类。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-21
      • 1970-01-01
      • 2020-09-05
      相关资源
      最近更新 更多