MKMapView userTrackingMode сбрасывается в SwiftUI - PullRequest
1 голос
/ 17 апреля 2020

У меня проблемы с отображением MKMapView в SwiftUI с userTrackingMode, установленным на .follow. Я показываю карту с:

struct ContentView: View {
    var body: some View {
        MapView()
    }
}

И в этом MapView я (а) устанавливаю userTrackingMode и (б), чтобы убедиться, что у меня есть разрешения при использовании. Я делаю такую ​​модель постоянно в проектах на основе раскадровки. В любом случае, MapView теперь выглядит следующим образом:

final class MapView: UIViewRepresentable {
    private lazy var locationManager = CLLocationManager()

    func makeUIView(context: Context) -> MKMapView {
        if CLLocationManager.authorizationStatus() == .notDetermined {
            locationManager.requestWhenInUseAuthorization()
        }

        let mapView = MKMapView()
        mapView.showsUserLocation = true
        mapView.userTrackingMode = .follow  // no better is mapView.setUserTrackingMode(.follow, animated: true)
        return mapView
    }

    func updateUIView(_ uiView: UIViewType, context: Context) {
        print(#function, uiView.userTrackingMode)
    }
}

Здесь все выглядит хорошо, но карта (как на симуляторе, так и на физическом устройстве) фактически не находится в режиме отслеживания подписчиков.

Итак, я расширил вышеупомянутое, чтобы добавить координатор, который принимает протокол MKMapViewDelegate, чтобы я мог наблюдать за тем, что происходит с режимом отслеживания:

final class MapView: UIViewRepresentable {
    private lazy var locationManager = CLLocationManager()

    func makeUIView(context: Context) -> MKMapView {
        if CLLocationManager.authorizationStatus() == .notDetermined {
            locationManager.requestWhenInUseAuthorization()
        }

        let mapView = MKMapView()
        mapView.delegate = context.coordinator
        mapView.showsUserLocation = true
        mapView.userTrackingMode = .follow  // no better is mapView.setUserTrackingMode(.follow, animated: true)
        return mapView
    }

    func updateUIView(_ uiView: UIViewType, context: Context) {
        print(#function, uiView.userTrackingMode)
    }

    func makeCoordinator() -> MapViewCoordinator {
        return MapViewCoordinator(self)
    }
}

class MapViewCoordinator: NSObject {
    var mapViewController: MapView

    var token: NSObjectProtocol?

    init(_ control: MapView) {
        self.mapViewController = control
    }
}

extension MapViewCoordinator: MKMapViewDelegate {
    func mapView(_ mapView: MKMapView, didChange mode: MKUserTrackingMode, animated: Bool) {
        print(#function, mode)
    }
}

В результате:

mapView(_:didChange:animated:) MKUserTrackingMode.follow
updateUIView(_:context:) MKUserTrackingMode.follow
mapView(_:didChange:animated:) MKUserTrackingMode.none

Происходит что-то, что сбрасывает userTrackingMode на .none.

Для хихиканья и усмешки я попытался сбросить userTrackingMode, и это не лучше:

func updateUIView(_ uiView: UIViewType, context: Context) {
    print(#function, uiView.userTrackingMode)
    uiView.userTrackingMode = .follow
}

Этот неуклюжий шаблон работает, хотя:

func updateUIView(_ uiView: UIViewType, context: Context) {
    print(#function, uiView.userTrackingMode)
    DispatchQueue.main.async {
        uiView.userTrackingMode = .follow
    }
}

Или все, что сбрасывает userTrackingMode позже, после этого начального процесса, также, кажется, работает.

Я что-то делаю не так с UIViewRepresentable? Ошибка в MKMapView?


Это не очень важно, но это моя процедура отображения режимов отслеживания:

extension MKUserTrackingMode: CustomStringConvertible {
    public var description: String {
        switch self {
        case .none:              return "MKUserTrackingMode.none"
        case .follow:            return "MKUserTrackingMode.follow"
        case .followWithHeading: return "MKUserTrackingMode.followWithHeading"
        @unknown default:        return "MKUserTrackingMode unknown/default"
        }
    }
}

1 Ответ

0 голосов
/ 17 апреля 2020

Ужасно, затрачивая непомерное количество времени на отладку этого, подготовку вопроса и т. Д. c., Похоже, что это странное поведение проявляется, только если вы не указали frame во время инициализации:

let mapView = MKMapView()

Когда я использовал следующее (хотя конечная карта не такого размера), оно работало правильно:

let mapView = MKMapView(frame: UIScreen.main.bounds)

Я все еще опубликую это в надежде, что это спасет кого-то другого из этого кошмара.

...