Search code examples
swiftcoordinatesmkmapview

How to replace new location coordinates in current location coordinates in MKMapView in swift


I am using map in Two viewcontrollers

Initially in first viewcontroller i am getting current location in map..

in second viewcontroller i am getting new location coordinates, which i am sending to firstview controller using delegate.. but here how to replace the delegate method coordinates with current location coordinates in first view controller

first view controller code: here in delegate method i am successfully having new location coordinates which i need replace with current location

in userDidEnterInformationdelegate method i am getting all values from 2nd view controller

import UIKit
import CoreLocation
import MapKit
class ProfileAddressViewController: UIViewController, CLLocationManagerDelegate, UISearchBarDelegate, DataEnteredDelegate {
var coordinate: CLLocationCoordinate2D = CLLocationCoordinate2D()
let locationManager = CLLocationManager()
var latitude: Double?
var logitude: Double?

@IBOutlet weak var mapView: MKMapView!

override func viewDidLoad() {
    super.viewDidLoad()
    
    self.locationManager.requestAlwaysAuthorization()
    if CLLocationManager.locationServicesEnabled() {
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
        locationManager.startUpdatingLocation()
    }
}

func userDidEnterInformation(info: DataEnteredModelSave) {
    print("map address viewcontroller data \(info)")
    self.pincodeField.text = info.pinCode
    self.cityField.text = info.cityField
    self.latitude = info.zLatitude
    self.self.logitude = info.zLongitude
    print("new map address viewcontroller data info lat long \(self.latitude) \(self.logitude)")
}
    
@IBAction func submitButtonClicked(_ sender: UIButton) {
    self.view.endEditing(true)
    
    let viewController = self.storyboard?.instantiateViewController(withIdentifier: "NewZoomAddressViewController") as! NewZoomAddressViewController;
   self.navigationController?.pushViewController(viewController, animated: true);
}

func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
    print(error)
}

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    guard let _: CLLocationCoordinate2D = manager.location?.coordinate else { return }
    
    let userLocation :CLLocation = locations.last! as CLLocation
    latitude = userLocation.coordinate.latitude
    logitude = userLocation.coordinate.longitude
    let geocoder = CLGeocoder()
    geocoder.reverseGeocodeLocation(userLocation) { (placemarks, error) in
        if (error != nil){
            print("error in reverseGeocode")
        }
        let placemark = placemarks! as [CLPlacemark]
                    
        if placemark.count>0{
            let placemark = placemarks![0]
            let placemarkDictonary: NSDictionary=placemark.addressDictionary as! NSDictionary
            self.pincodeField.text=placemarkDictonary["ZIP"] as? String
            self.cityField.text=placemarkDictonary["City"] as? String
        }
    }
    
    let center = CLLocationCoordinate2D(latitude: latitude!, longitude: logitude!)
    let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
    mapView.setRegion(region, animated: true)
    let myAnnotation: MKPointAnnotation = MKPointAnnotation()
    myAnnotation.coordinate = CLLocationCoordinate2DMake(userLocation.coordinate.latitude, userLocation.coordinate.longitude);
    myAnnotation.title = "Current location"
    mapView.addAnnotation(myAnnotation)
}
}

please help me to add delegate method latitude and longitude in locationManager didUpdateLocations


Solution

  • Replace userDidEnterInformation with below code:

    func userDidEnterInformation(info: DataEnteredModelSave) {
        print("map address viewcontroller data \(info)")
        self.pincodeField.text = info.pinCode
        self.streetField.text = info.streetField
        self.cityField.text = info.cityField
        self.latitude = info.zLatitude
        self.logitude = info.zLongitude
        print("map address viewcontroller data info lat long \(self.latitude) \(self.logitude)")
        
        locationManager.stopUpdatingLocation() //stop updating location when you got data from delegate
        
        let userLocation = CLLocation.init(latitude: latitude!, longitude: logitude!)
        
        let geocoder = CLGeocoder()
        geocoder.reverseGeocodeLocation(userLocation) { (placemarks, error) in
            if (error != nil){
                print("error in reverseGeocode")
            }
            let placemark = placemarks! as [CLPlacemark]
            
            if placemark.count>0{
                let placemark = placemarks![0]
                print(placemark.locality!)
                print(placemark.administrativeArea!)
                print(placemark.country!)
                let placemarkDictonary: NSDictionary=placemark.addressDictionary as! NSDictionary
                self.pincodeField.text=placemarkDictonary["ZIP"] as? String
                self.cityField.text=placemarkDictonary["City"] as? String
                self.plotField.text=placemarkDictonary["Name"] as? String
                self.streetField.text=placemarkDictonary["Street"] as? String
                self.appormentNoField.text=placemarkDictonary["SubThoroughfare"] as? String
                self.colonyField.text=placemarkDictonary["SubLocality"] as? String
                self.landmarkField.text=placemarkDictonary["SubThoroughfare"] as? String
            }
        }
        
        let center = CLLocationCoordinate2D(latitude: latitude!, longitude: logitude!)
        
        //Assign data to map again with new location
        let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
        mapView.setRegion(region, animated: true)
        let myAnnotation: MKPointAnnotation = MKPointAnnotation()
        myAnnotation.coordinate = CLLocationCoordinate2DMake(latitude!, logitude!)
        myAnnotation.title = "Current location"
        mapView.addAnnotation(myAnnotation)
    }
    

    I have added comments please check them.

    EDIT: As per your second request if you want to show new coordinates on NewZoomAddressViewController first you need to pass coordinates to NewZoomAddressViewController in submitButtonClicked method like:

    viewController.latestLocation = CLLocation.init(latitude: self.latitude!, longitude: self.logitude!)
    

    then in NewZoomAddressViewController declare new var

    var latestLocation: CLLocation?
    

    and remove other code which is related to user's current location and final code will look like:

    import UIKit
    import MapKit
    import CoreLocation
    //import SwiftKeychainWrapper
    protocol DataEnteredDelegate: class {
        func userDidEnterInformation(info: DataEnteredModelSave)
    }
    
    class NewZoomAddressViewController: UIViewController {
           
        @IBOutlet weak var oneBtnContainerView: UIView!
        
        var latitudeZoom: Double?
        var logitudeZoom: Double?
        
        weak var delegate: DataEnteredDelegate? = nil
       
        var zipName: String?
        var localityName: String?
        var sublocalityName: String?
        var streetNumber: String?
        var streetName: String?
        
        
        let searchCont = UISearchController(searchResultsController: nil)
        let annotation = MKPointAnnotation()
        
        
        @IBOutlet weak var mapView: MKMapView!
        @IBOutlet weak var addressLabel: UILabel!
        
        let regionInMeters: Double = 10000
        var previousLocation: CLLocation?
        var latestLocation: CLLocation?
        
        override func viewDidLoad() {
            super.viewDidLoad()
            print("in Zoom map VC")
            
            mapView.delegate = self
            addressLabel.text = "\(self.sublocalityName!) \(localityName!) \(self.zipName!)"
            centerViewOnUserLocation()
            
        }
        @IBAction func backBtn(_ sender: Any) {
               self.navigationController?.popViewController(animated: true)
           }
        override func viewWillAppear(_ animated: Bool) {
            self.navigationController?.navigationBar.isHidden=true
            
            
        }
        
        var viewController: UIViewController?
        
        
        
        @IBAction func confirmBtn(_ sender: Any) {
            
            guard
                         let zipName = zipName,
                         let sublocalityName = sublocalityName,
                         let localityName = localityName,
                         let lnatZ = latitudeZoom,
                         let longZ = logitudeZoom
          
                         else { return }
            let enteredData = DataEnteredModelSave(pinCode: zipName, streetField: sublocalityName, cityField: localityName, zLatitude: lnatZ, zLongitude: longZ)
                     delegate?.userDidEnterInformation(info: enteredData)
                  
                  self.navigationController?.popViewController(animated: true)
        }
        
        func centerViewOnUserLocation() {
            if let location = latestLocation {
                let region = MKCoordinateRegion.init(center: location.coordinate, latitudinalMeters: regionInMeters, longitudinalMeters: regionInMeters)
                mapView.setRegion(region, animated: true)
            }
        }
        
        func getCenterLocation(for mapView: MKMapView) -> CLLocation {
            latitudeZoom = mapView.centerCoordinate.latitude
          logitudeZoom = mapView.centerCoordinate.longitude
            
           
            print("coordinates from zoom in func \(latitudeZoom), \(logitudeZoom)")
            
            return CLLocation(latitude: latitudeZoom!, longitude: logitudeZoom!)
            //print(CLLocation.self)
        }
    }
    
    
    
    extension NewZoomAddressViewController: CLLocationManagerDelegate, UISearchBarDelegate {
        
        //    MARK:- Search Address
        @IBAction func searchLocationButton(_ sender: Any) {
           // let searchCont = UISearchController(searchResultsController: nil)
            searchCont.searchBar.delegate = self
            searchCont.searchBar.backgroundColor = .blue
            present(searchCont, animated:true, completion:nil)
        }
        
        func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
            searchBar.resignFirstResponder()
            dismiss(animated: true, completion: nil)
            //create the search request
            let searchReq = MKLocalSearch.Request()
            searchReq.naturalLanguageQuery = searchBar.text
            let activeSearch = MKLocalSearch(request: searchReq)
            activeSearch.start { (response, error) in
                UIApplication.shared.endIgnoringInteractionEvents()
                if response == nil{
                    print("error")
                }
                else{
                    //remove annotation
                    //let annotations = self.mapView.annotations
                   // self.mapView.removeAnnotation(annotations as! MKAnnotation)
                    //getting data
                    let lat = response?.boundingRegion.center.latitude
                    let long = response?.boundingRegion.center.longitude
                    //create annotation
                    //let annotation = MKPointAnnotation()
                    self.annotation.title = searchBar.text
                    self.annotation.coordinate = CLLocationCoordinate2DMake(lat!, long!)
                    self.mapView.addAnnotation(self.annotation)
                    //zooming annotation
                    let coordinate: CLLocationCoordinate2D = CLLocationCoordinate2DMake(lat!, long!)
                    let span = MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)
                    let region = MKCoordinateRegion(center: coordinate, span: span)
                    self.mapView.setRegion(region, animated: true)
                    
                    
                    // Add below code to get search address
                    let geoCoder = CLGeocoder()
                    let location = CLLocation(latitude: lat!, longitude: long!)
                          geoCoder.reverseGeocodeLocation(location, completionHandler:
                              {
                                  placemarks, error -> Void in
    
                                  // Place details
                                  guard let placeMark = placemarks?.first else { return }
    
                                  // Location name
                                
                                self.zipName = placeMark.postalCode
                                self.localityName = placeMark.locality
                                self.sublocalityName = placeMark.subLocality
                                self.streetNumber = placeMark.subThoroughfare
                                self.streetName = placeMark.thoroughfare
                               
    
                          })
                }
            }
        }
        
        
        
    }
    
    
    extension NewZoomAddressViewController: MKMapViewDelegate {
        
        func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
            let center = getCenterLocation(for: mapView)
            let geoCoder = CLGeocoder()
            
            guard let previousLocation = self.latestLocation else { return }
            
            guard center.distance(from: previousLocation) > 50 else { return }
            self.previousLocation = center
            
            
            
            let userLocation :CLLocation = center as CLLocation
            latitudeZoom = userLocation.coordinate.latitude
            logitudeZoom = userLocation.coordinate.longitude
            
            
            print("snajxhdwuidhwiuqhdxiqwjmdio \(latitudeZoom), \(logitudeZoom)")
            
            
            geoCoder.reverseGeocodeLocation(center) { [weak self] (placemarks, error) in
                guard let self = self else { return }
                
                if let _ = error {
                    //TODO: Show alert informing the user
                    return
                }
                
                guard let placemark = placemarks?.first else {
                    //TODO: Show alert informing the user
                    return
                }
                
                
               self.streetNumber = placemark.subThoroughfare ?? ""
                self.streetName = placemark.thoroughfare ?? ""
                
                
                print("street number of zoom map \(self.streetName)")
                
                self.localityName = placemark.locality ?? ""//locality
                self.sublocalityName = placemark.subLocality ?? ""//locality
                self.zipName = placemark.postalCode ?? ""//locality
                
                
                
                DispatchQueue.main.async {
                    self.addressLabel.text = "\(self.streetNumber ?? "") \(self.streetName ?? "") \(self.sublocalityName ?? "") \(self.zipName ?? "") \(self.localityName ?? "")"
                    print("zzooom map location label \(self.addressLabel.text)")
       
                    
                }
            }
        }
    }