Добавьте действие к кнопке в MKPinAnnotationView

#ios #swift #uibutton #userdefaults #mkpinannotationview

Вопрос:

tldr: Я пытаюсь добавить действия с предупреждениями к кнопке в pinView и сохранить эти данные (имена контактов с описанием и значком pin-кода) в UserDefaults. У меня есть булавки с MKPinAnnotationView и кнопкой в нем. Я хотел бы, чтобы эта кнопка проверяла, находится ли пользователь более или менее чем в 100 метрах от места размещения pin-кода. После нажатия кнопки (когда пользователь находится В радиусе 100 м от местоположения pin-кода) он должен показать UIAlertController (в противном случае он должен отображать аналогичное предупреждение, как показано ниже, с информацией о том, что пользователь находится за пределами радиуса, например, с помощью простого действия отмены):

 let alertController = UIAlertController(title: "Check-in!", message: "Click below to check-in", preferredStyle: UIAlertController.Style.alert)

alertController.addAction(UIAlertAction(title: "Check-In", style: UIAlertAction.Style.default, handler: { action in  //HERE I WOULD LIKE TO SAVE THE NAME OF THE PIN SOMEWHERE IN UserDefaults to display it later in table view in another ViewController))

alertController.addAction(UIAlertAction(title: "Cancel", style: UIAlertAction.Style.default, handler: { action in  //close alert and do nothing))
 

Вот мой код:

 import UIKit
import MapKit


class ViewController: UIViewController, MKMapViewDelegate{

    let locationManager = CLLocationManager()

    struct Szczyt {
      let name: String
      let opis: String
      let lattitude: CLLocationDegrees
      let longtitude: CLLocationDegrees
        var coordinate: CLLocationCoordinate2D {
            .init(latitude: lattitude, longitude: longtitude)
        }
    }

    @IBOutlet weak var mapView: MKMapView!
    @IBAction func mapTypeSegmentSelected(_ sender: UISegmentedControl) {
            switch sender.selectedSegmentIndex {
            case 0:
                mapView.mapType = .standard
            case 1:
                mapView.mapType = .satellite
            default:
                mapView.mapType = .hybrid
            }
        }
    private(set) var circles: [MKCircle]!

    let szczyty = [Szczyt(name: "one", opis: "describtion", lattitude: 53.865061725039226, longtitude:   17.708595782487315),
                   Szczyt(name: "two", opis: "describtion2", lattitude: 55.893874478583854, longtitude: 24.896341184611302),
                   Szczyt(name: "Skrzyczne", opis: "describtion3", lattitude: 49.685059170137386, longtitude: 19.030076144463138)]


    override func viewDidLoad() {
        super.viewDidLoad()
        mapView.register(MKMarkerAnnotationView.self, forAnnotationViewWithReuseIdentifier: "identifier")
        checkLocationServices()
        znajdzSzczytyNaMapie(szczyty)
        circles = szczyty.map {
                    MKCircle(center: $0.coordinate, radius: 100)
                }
        mapView.addOverlays(circles!)
        mapView.delegate = self
        }






        func checkLocationServices() {
          if CLLocationManager.locationServicesEnabled() {
            checkLocationAuthorization()
          } else {
            // Show alert letting the user know they have to turn this on.
          }
        }
        func checkLocationAuthorization() {
          switch CLLocationManager.authorizationStatus() {
          case .authorizedWhenInUse:
            mapView.showsUserLocation = true
           case .denied: 
           break
          case .notDetermined:
            locationManager.requestWhenInUseAuthorization()
            mapView.showsUserLocation = true
          case .restricted: 
           break
          case .authorizedAlways:
           break

          }
    }
    func znajdzSzczytyNaMapie(_ szczyty: [Szczyt]) {
      for szczyt in szczyty {
        let annotations = MKPointAnnotation()
        annotations.title = szczyt.name
        annotations.subtitle = szczyt.opis
        annotations.coordinate = CLLocationCoordinate2D(latitude:
          szczyt.lattitude, longitude: szczyt.longtitude)
        mapView.addAnnotation(annotations)
      }
    }
let location = CLLocation()
let circleCenter = CLLocation()
//This I think is necessary for detecting if user is in 100m distance from the location - Is it good?:if location.distance(from: circleCenter) < circleRadius {
    // User is inside radius 100m.
//}


func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
        guard !(annotation is MKUserLocation) else { return nil }
        mapView.delegate = self
        let annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: String(annotation.hash))
        let identifier = "identifier"
        annotationView.canShowCallout = true
        guard let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier, for: annotation) as? MKMarkerAnnotationView else { return nil }
        let rightButton = UIButton(type: .contactAdd)
        rightButton.tag = annotation.hash
        annotationView.canShowCallout = true
        annotationView.rightCalloutAccessoryView = rightButton

//HERE IS THIS BUTTON called rightButton that I need action with alerts.

switch annotation.title!! {
            case "one":
                annotationView.markerTintColor = UIColor(red: 0.86, green: 0.99, blue: 0.79, alpha: 1.00)
                annotationView.glyphImage = UIImage(named: "one_pic")
            case "two":
                annotationView.markerTintColor = UIColor(red: 0.80, green: 0.98, blue: 0.73, alpha: 1.00)
                annotationView.glyphImage = UIImage(named: "two_pic"")
            case "Skrzyczne":
                annotationView.markerTintColor = UIColor(red: 0.02, green: 0.61, blue: 0.69, alpha: 1.00)
                annotationView.glyphImage = UIImage(named: "three_pic"")
            default:
                annotationView.markerTintColor = UIColor.green
                annotationView.glyphImage = UIImage(named: "default")
        }
        return annotationView
    }
    func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
        let circleRenderer = MKCircleRenderer(overlay: overlay)
        circleRenderer.strokeColor = UIColor.green
        circleRenderer.fillColor = UIColor.green
        circleRenderer.alpha = 0.3
        circleRenderer.lineWidth = 1.0
        return circleRenderer
    }


}
 

Для этих сохраненных данных с именами я создал второй ViewController, чтобы сохранить их в виде таблицы.

Если что-то непонятно, пожалуйста, спросите 🙂 Заранее спасибо.

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

1. «100 метров образуют КЛОкокацию штифта»? «когда пользователь НАХОДИТСЯ ВНУТРИ местоположения пин-кода радиусом 100 м», что это за вещь, которую вы так называете местоположением пин-кода радиусом 100 м?

2. @Эль Помидор circles = szczyty.map { MKCircle(center: $0.coordinate, radius: 100) Дело в том, что его можно использовать с оператором if, который я прокомментировал.

3. @El Tomato есть какие-нибудь предложения? Заранее спасибо.

4. Я не смогу вам помочь, пока вы не исправите свои опечатки.