How to store users data - saving reached locations name

Hello,

I would like to store, save users data inside the app (Best option to store it in the cloud) with location the user reach. The loaction check in point on the map is within radius 100 meters. So the thing I would like to do is to show as a list in the second viewcontroller Zdobyte Szczyty, names of the locations sczyt.name from the first ViewController (the one with the map) that user reached (clicked with a button to check in). I thought about adding a button to the annotation view, which should do the check in if the user is in this radius - but it does not show me the button, just pin. Here is my code:

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: // Show alert telling users how to turn on permissions
           break
          case .notDetermined:
            locationManager.requestWhenInUseAuthorization()
            mapView.showsUserLocation = true
          case .restricted: // Show an alert letting them know what’s up
           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)
      }
    }

    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
        guard !(annotation is MKUserLocation) else { return nil }
        //let annotationView = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: "MyMarker")
        let identifier = "identifier"
        //guard let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? MKMarkerAnnotationView else { return nil }
        guard let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier, for: annotation) as? MKMarkerAnnotationView else { return nil }
        let btn = UIButton(type: .detailDisclosure)
        annotationView.rightCalloutAccessoryView = btn
        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
    }


}

This is my Zdobyte Szczyty viewcontroller:

import UIKit

import SwiftUI



class Zdobyte_ViewController: UIViewController {



    struct ContentView: View {

        var body: some View {

           Text("Test viewcontroller gór")

    }

    }

    override func viewDidLoad() {

        super.viewDidLoad()

    }

    



}

Here is the button view I would like to have with the pin image, but now it only shows the pin with the image:

This is how my viewcontrollers view looks like:

Answered by Claude31 in 690321022

Here is how to add a button to annotation:

https://stackoverflow.com/questions/41495956/how-to-add-button-to-mkpointannotation-in-swift

That seems close to what you've done, as MKPinAnnotationView is deprecated.

Or more recent:

https://stackoverflow.com/questions/57086152/how-do-i-add-button-to-mkpointannotation-in-swift

Replace as well MKPinAnnotationView

Accepted Answer

Here is how to add a button to annotation:

https://stackoverflow.com/questions/41495956/how-to-add-button-to-mkpointannotation-in-swift

That seems close to what you've done, as MKPinAnnotationView is deprecated.

Or more recent:

https://stackoverflow.com/questions/57086152/how-do-i-add-button-to-mkpointannotation-in-swift

Replace as well MKPinAnnotationView

Important lines are those (canShowCallout = true):

        pinView?.canShowCallout = true

        let rightButton: AnyObject! = UIButton(type: UIButton.ButtonType.detailDisclosure)
        pinView?.rightCalloutAccessoryView = rightButton as? UIView

You could store those date

  • in UserDefaults (if the list is not excessively long).
var myArrayOfPoints : [CLLocationCoordinate2D] = []  // I think it is CLLocationCoordinate2D, check it. You may prefer to save Strings of names ?
        let defaults = UserDefaults.standard
        defaults.set(myArrayOfPoints, forKey: "PointsOfInterestKey")

Then you can retrieve easily from anywhere in app, and it is saved when you close app or even update the app.

        let defaults = UserDefaults.standard
        myArrayOfPoints = defaults.string(forKey: "PointsOfInterestKey") ?? []
  • Or in a local file.
How to store users data - saving reached locations name
 
 
Q