Аннотации MapKit Исчезают

#ios #swift #mapkit #mapkitannotation

#iOS #swift #mapkit #mapkitannotation

Вопрос:

У меня есть массив широт и другой массив долгот, которые я добавляю в массив типа CLLocationCoordinate2D. Затем я использую новый массив для аннотирования нескольких точек на карте. Некоторые, или большинство, или, может быть, даже все аннотации отображаются на карте, но когда я увеличиваю масштаб (да, увеличиваю масштаб), некоторые аннотации исчезают, затем возвращаются или нет. Есть какие-нибудь идеи о том, как сделать их все видимыми? Это поведение, которое я ожидал бы при уменьшении масштаба, а не при увеличении.

Вот код, который я использую для того, что я описал выше.

 import UIKit
import MapKit
import CoreLocation

class MultiMapVC: UIViewController, CLLocationManagerDelegate {

@IBOutlet weak var multiEventMap: MKMapView!

var latDouble = Double()
var longDouble = Double()
let manager = CLLocationManager()
var receivedArrayOfLats = [Double]()
var receivedArrayOfLongs = [Double]()
var locations = [CLLocationCoordinate2D]()


func locationManager(_ manager: CLLocationManager, didUpdateLocations uLocation: [CLLocation]) {
    let userLocation = uLocation[0]
    let span:MKCoordinateSpan = MKCoordinateSpanMake(0.3, 0.3)
    let usersLocation = userLocation.coordinate
    let region:MKCoordinateRegion = MKCoordinateRegionMake(usersLocation, span)
    multiEventMap.setRegion(region, animated: true)
    manager.distanceFilter = 1000
    self.multiEventMap.showsUserLocation = true
}

func multiPoint() {

    var coordinateArray: [CLLocationCoordinate2D] = []
    print ("Received Longitude Count = (receivedArrayOfLongs.count)")
    print ("Received Latitude Count = (receivedArrayOfLats.count)")
    if receivedArrayOfLats.count == receivedArrayOfLongs.count {
        for i in 0 ..< receivedArrayOfLats.count {
            let eventLocation = CLLocationCoordinate2DMake(receivedArrayOfLats[i], receivedArrayOfLongs[i])
            coordinateArray.append(eventLocation)
            print (coordinateArray.count)
        }
    }

    for events in coordinateArray {
        let annotation = MKPointAnnotation()
        annotation.coordinate = CLLocationCoordinate2D(latitude: events.latitude, longitude: events.longitude)
        multiEventMap.addAnnotation(annotation)
        }
}


override func viewDidLoad() {
    super.viewDidLoad()
    manager.delegate = self
    manager.desiredAccuracy = kCLLocationAccuracyBest
    manager.requestWhenInUseAuthorization()
    manager.startUpdatingLocation()
    multiPoint()
        }


override func viewDidDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)
    multiEventMap.removeFromSuperview()
    self.multiEventMap = nil

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}
 

}

Комментарии:

1. Пожалуйста, поделитесь своим кодом метода аннотации viewFor

2. Я сталкиваюсь с той же проблемой, похоже, она присутствует только в iOS 11.

3. Я обновился, чтобы включить весь код из моего VC .. Однако у меня нет метода viewForAnnotation.

4. Это все еще происходит на iOS 13.

Ответ №1:

Решение NiltiakSivad работает, но оно возвращается к старому виду iOS 10. Если вы хотите сохранить новые маркеры воздушных шаров iOS 11 для iOS 11 и использовать старый pin-код, ищите только более старые версии iOS, тогда вы можете реализовать метод делегирования, как показано ниже:

 func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
    let reuseIdentifier = "annotationView"
    var view = mapView.dequeueReusableAnnotationView(withIdentifier: reuseIdentifier)
    if #available(iOS 11.0, *) {
        if view == nil {
            view = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: reuseIdentifier)
        }
        view?.displayPriority = .required
    } else {
        if view == nil {
            view = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseIdentifier)
        }
    }
    view?.annotation = annotation
    view?.canShowCallout = true
    return view
}
 

Комментарии:

1. На самом деле, вероятно, это ошибка Apple, поскольку приоритет отображения по умолчанию должен быть .required (но, по-видимому, это не так!)

2. (Кстати, вы не должны ссылаться на другой ответ как «выше» или «ниже», поскольку их порядок меняется в зависимости от их оценок. Вместо этого вы должны написать «решение NiltiakSivad». Я соответствующим образом отредактирую ваш ответ.)

Ответ №2:

Принятый ответ от Лешека Сары правильный.

Но есть некоторые нюансы. Иногда MKMarkerAnnotationView s не отображаются, даже если

 view.displayPriority = .required
 

установлено.

То, что вы видите, представляет собой комбинацию разных правил.

  1. MKAnnotationViews отображаются сверху вниз карты. (Не имеет значения, где находится север).
  2. Если MapKit вы решите нарисовать перекрытие MKAnnotationViews , то MKAnnotationView более близкое к низу будет нарисовано сверху (потому что оно будет нарисовано позже)
  3. Мало того MKAnnotationViews , что заголовки, отображаемые ниже MKMArkerAnnotationViews , нуждаются в пространстве. На отображение этих заголовков влияет markerView.titleVisibility . Если markerView.titleVisibility установлено значение .visible (вместо значения по умолчанию .adaptive ), то этот заголовок сильнее, чем a MarkerAnnotationView , который отображается позже, даже если у более позднего MarkerAnnotationView есть a displayPriority = .required . MarkerAnnotationView Ближе к нижней части не отображается.
  4. Это происходит даже в том случае, если MarkerAnnotationView ближе к вершине имеет низкий displayPriority уровень. Таким образом, a MarkerAnnotationView с низким displayPriority и .titleVisibility = .visible может MarkerAnnotationView приблизиться к низу с displayPriority = .required исчезновением.

Я не знаю документации об этом поведении. Это результат моих экспериментов с iOS 12. Мое описание sipmplified.

Ответ №3:

Я столкнулся с аналогичной проблемой. Я предполагаю, что это как-то связано с тем, как iOS 11 обнаруживает столкновения контактов. Реализация пользовательского представления аннотаций или возврат к использованию pin-кода iOS 10 устранили проблему для меня.

Например, реализация следующего должна исправить ваш код:

 class MultiMapVC: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
   override func viewDidLoad() {
       super.viewDidLoad()
       mapView.delegate = self    
    }

    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
       guard let annotation = annotation as? MKPointAnnotation else { return nil }

       let identifier = "pin-marker"
       var view: MKAnnotationView

       if let dequeuedView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? MKPinAnnotationView {
           dequeuedView.annotation = annotation
           view = dequeuedView
       } else {
           view = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
       }
       return view
   }
}
 

Если это не работает, есть displayPriority свойство, на которое стоит обратить внимание, поскольку оно отвечает за то, чтобы помочь определить, когда контакты должны быть скрыты / показаны на разных уровнях масштабирования. Больше информации на https://developer.apple.com/documentation/mapkit/mkannotationview/2867298-displaypriority

Надеюсь, это поможет.

Комментарии:

1. Это работает! Одна вещь, которую я заметил, это то, что эти выводы нельзя выбрать.

Ответ №4:

Я устанавливал annotationView.displayPriority = .required только тогда, когда MKMarkAnnotationView был впервые выделен. Обычно это все, что вам нужно сделать, но установка этого параметра каждый раз при повторном использовании ячейки устранила проблему для меня.

Ответ №5:

Я видел аналогичную проблему с Xcode 10 и iOS 12 в качестве моей цели развертывания. Сообщение от сотрудника Apple (https://forums.developer.apple.com/thread/92839 ) рекомендует переключить .isHidden свойство на удаленном из очереди маркере. Это улучшило ситуацию, но не полностью решило проблему.

 result?.isHidden = true
result?.isHidden = false
return result