Показ мест на карте

swift
xcode
ios

#1

Привет! У меня есть MapView, хочу обращаясь к ней показывать определенные места на карте по координатам сохраненным в памяти.Вопрос в том, как показать на карте опр. места по координатам. Благодарствую!


#2

Простой пример как сделать карту как у меня на рисунке:

  1. Определяем свой MKAnnotationView и MKAnnotation

    import UIKit
    import MapKit

    class CUAnnotationView: MKAnnotationView {

    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
    let hitView = super.hitTest(point, with: event)
    if (hitView != nil) {
    self.superview?.bringSubview(toFront: self)
    }
    return hitView
    }

    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
    let rect = self.bounds;
    var isInside: Bool = rect.contains(point)
    if (!isInside) {
    for view in self.subviews {
    isInside = view.frame.contains(point)
    if isInside {
    break;
    }
    }
    }
    return isInside;
    }

    }

  2. В классе с нашей картой

  • Подписываемся под протокол MKMapViewDelegate

  • Настраиваем саму карту

@IBOutlet weak var mapView: MKMapView? {
    didSet {
      mapView?.delegate        = self
      mapView?.mapType         = .standard
      mapView?.isPitchEnabled  = false
      mapView?.isRotateEnabled = false
      mapView?.isScrollEnabled = true
      mapView?.isZoomEnabled   = true
    }
  }
  1. На камеру добавляем наши кастомные вьюшки по координатам:

    if coordinates.count > 0 {
    for cam in coordinates.count {
    let point = CUCamsAnnotation(coordinate: CLLocationCoordinate2D(latitude: cam.latitude,
    longitude: cam.longitude))
    point.image = #imageLiteral(resourceName: “web_camera_location”)
    point.number = cam.number
    point.address = cam.name
    point.client = false
    mapView?.addAnnotation(point)
    }
    }

  2. Устанавливаем регион отображения, чтоб все наши вьюшки поместились и были видны одновременно:

    mapView?.fitMapViewToAnnotaionList()

с помощью такого расширения:

extension MKMapView {
  
  func fitMapViewToAnnotaionList() -> Void {
    let mapEdgePadding = UIEdgeInsets(top: 40, left: 40, bottom: 40, right: 40)
    var zoomRect:MKMapRect = MKMapRectNull
    for index in 0..<self.annotations.count {
      let annotation = self.annotations[index]
      let aPoint:MKMapPoint = MKMapPointForCoordinate(annotation.coordinate)
      let rect:MKMapRect = MKMapRectMake(aPoint.x, aPoint.y, 0.1, 0.1)
      if MKMapRectIsNull(zoomRect) {
        zoomRect = rect
      } else {
        zoomRect = MKMapRectUnion(zoomRect, rect)
      }
    }
    self.setVisibleMapRect(zoomRect, edgePadding: mapEdgePadding, animated: true)
  }
  
}
  1. Сообщаем, что используем не пин, а свою кастомную вьюшку с нашим изображением:

    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
    if annotation is MKUserLocation { return nil }
    var annotationView = self.mapView?.dequeueReusableAnnotationView(withIdentifier: “Pin”)
    if annotationView == nil{
    annotationView = CUAnnotationView(annotation: annotation, reuseIdentifier: “Pin”)
    annotationView?.canShowCallout = false
    }
    else { annotationView?.annotation = annotation }
    annotationView?.image = #imageLiteral(resourceName: “web_camera_location”)
    return annotationView
    }

Чтобы сделать такую вьюшку для детализации:

  • Создадим xib-файл и настроим нашу вьюшку как душе угодно. Можно использовать что угодно… лейблы, имиджи, свичи, кнопки и так далее

Ну и сам классы для нее

import UIKit

class CUDetailCamView: UIView {

  @IBOutlet weak var address: UILabel?
  @IBOutlet weak var image: UIImageView?
  
  @IBOutlet weak var backView: UIView? {
    didSet {
      backView?.layer.borderColor   = #colorLiteral(red: 0.9925034642, green: 0.8121734858, blue: 0, alpha: 1).cgColor
      backView?.layer.borderWidth   = 0.35
      backView?.layer.cornerRadius  = backView!.frame.size.height / 2
      backView?.layer.masksToBounds = true
    }
  }
  
  var number: String!
  var client: Bool!

}

В контроллере с камерой осталось добавить пару методов и все будет работать:

 func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
    if view.annotation is MKUserLocation { return }
    let detailAnnotation = view.annotation as! CUCamsAnnotation
    let views = Bundle.main.loadNibNamed("CUDetailCamView", owner: nil, options: nil)
    let detailtView = views?[0] as! CUDetailCamView
    detailtView.address?.text = detailAnnotation.address
    detailtView.number = detailAnnotation.number
    detailtView.client = detailAnnotation.client
    let button = UIButton(frame: detailtView.address!.frame)
    button.addTarget(self, action: #selector(CUMapsController.showStream(sender:)), for: .touchUpInside)
    detailtView.addSubview(button)
    detailtView.center = CGPoint(x: view.bounds.size.width / 2, y: -detailtView.bounds.size.height * 0.52)
    view.addSubview(detailtView)
    mapView.setCenter((view.annotation?.coordinate)!, animated: true)
  }
  
  func mapView(_ mapView: MKMapView, didDeselect view: MKAnnotationView) {
    if view.isKind(of: CUAnnotationView.self) {
      for subview in view.subviews {
        subview.removeFromSuperview()
      }
    }
  }

#3

Спасибо Вам, огромное! Это помогло!


#5

Извиняюсь за то что поднимаю тему :slight_smile:

Не могли бы добавить в решение реализацию протокола MKAnnotation ?

А лучше проект с этим всем)))


#6

Решение представлено выше. Там все понятно объясняется. Если есть конкретные вопросы - задавайте.