UIViewRepresentable: «Изменение состояния во время обновления представления, это приведет к неопределенному поведению» - PullRequest
0 голосов
/ 30 января 2020

Я сделал простой UIViewRepresentable из MKMapView. Вы можете прокрутить вид карты, и на экране появятся координаты посередине.

Вот ContentView:

import SwiftUI
import CoreLocation

let london = CLLocationCoordinate2D(latitude: 51.50722, longitude: -0.1275)

struct ContentView: View {
    @State private var center = london

    var body: some View {
        VStack {
            MapView(center: self.$center)
            HStack {
                VStack {
                    Text(String(format: "Lat: %.4f", self.center.latitude))
                    Text(String(format: "Long: %.4f", self.center.longitude))
                }
                Spacer()
                Button("Reset") {
                    self.center = london
                }
            }.padding(.horizontal)
        }
    }
}

Вот MapView:

struct MapView: UIViewRepresentable {
    @Binding var center: CLLocationCoordinate2D

    func makeUIView(context: Context) -> MKMapView {
        let mapView = MKMapView()
        mapView.delegate = context.coordinator
        return mapView
    }

    func updateUIView(_ uiView: MKMapView, context: Context) {
        uiView.centerCoordinate = self.center
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    class Coordinator: NSObject, MKMapViewDelegate {
        var parent: MapView

        func mapViewDidChangeVisibleRegion(_ mapView: MKMapView) {
            parent.center = mapView.centerCoordinate
        }

        init(_ parent: MapView) {
            self.parent = parent
        }
    }
}

Нажатие на кнопку сброса должно просто установить mapView.center в Лондон. Текущий метод сделает прокрутку карты очень медленной, а когда нажата кнопка, возникает ошибка «Изменение состояния во время обновления вида, это приведет к неопределенному поведению».

Как следует сообщать об изменении координат MKMapView, так что прокрутка карты снова быстро, и ошибка исправлена?

1 Ответ

0 голосов
/ 30 января 2020

Если вы поместите центральную переменную в наблюдаемый объект, проблема скорости будет решена. Это устраняет необходимость в асинхронном обновлении c, которое, вероятно, является причиной задержки.

import SwiftUI
import CoreLocation
import MapKit

//let london = CLLocationCoordinate2D(latitude: 51.50722, longitude: -0.1275)

class MapController: ObservableObject{
    @Published var center: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: 51.50722, longitude: -0.1275)
    func resetCenter(){
        center = CLLocationCoordinate2D(latitude: 51.50722, longitude: -0.1275)
    }
}
struct MapViewCenter: View {
    //@State private var center = london
    @ObservedObject var mapCont: MapController = MapController()
    @State var refresh: Bool = false
    var body: some View {
        VStack {
            MapView(refresh: $refresh, mapCont: mapCont)
            HStack {
                VStack {
                    Text(String(format: "Lat: %.4f", self.mapCont.center.latitude))
                    Text(String(format: "Long: %.4f", self.mapCont.center.longitude))
                }
                Spacer()
                Button("Reset") {
                    print("resetButton")
                    self.mapCont.resetCenter()
                    self.refresh.toggle()
                    print("resetButton :: center = \(self.mapCont.center)")
                }
            }.padding(.horizontal)
        }
    }
}
struct MapView: UIViewRepresentable {
    @Binding var refresh: Bool
    var mapCont: MapController

    func makeUIView(context: Context) -> MKMapView {
        let mapView = MKMapView()
        mapView.delegate = context.coordinator
        return mapView
    }

    func updateUIView(_ uiView: MKMapView, context: Context) {
        uiView.centerCoordinate = self.mapCont.center
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    class Coordinator: NSObject, MKMapViewDelegate {
        var parent: MapView
        func mapViewDidChangeVisibleRegion(_ mapView: MKMapView) {
            parent.mapCont.center = mapView.centerCoordinate
        }

        init(_ parent: MapView) {
            self.parent = parent
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...