1

UIViewRepresentable.updateUIView は、このビューとその親ビューが依存する ObservableObject が変更されたときに呼び出されません。

バインディングとして MapView に渡される "@State var locationManager: LocationManager" を持つ GameView があります。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() が呼び出されることを期待しています。実際には、ホームボタンごとにアプリを終了したとき(および再度入力したとき)にのみ呼び出しが発生します

4

1 に答える 1

0

このように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()別のクラスを呼び出す必要があると思います。

于 2019-12-20T09:32:33.377 に答える