Search code examples
swiftuiviewcontrollerdelegatesuitextfieldmkmapview

How to replace old value with new value from next view controller in MKMapView in Swift?


I have two map View controllers, in first view controller i am fetching current location and auto filling some values and showing them in related textfields.

And in second view controller i am searching new location and sending its location values to first view controller using DataEnteredDelegate method now how to replace delegate method values in current location values in first view controller.

here i am getting second view controller values:

func userDidEnterInformation(info: [String]) {
    print("zoom map address viewcontroller data \(info)")
}

Prints: zoom map address viewcontroller data '["560066", "Auto Nagar", "Bangalore"]'

how to replace 560066 in self.pincodeField.text and Auto Nagar in self.streetField.text and Bangalore in self.cityField.text in first view controller

first view controller code:

class ProfileAddressViewController: UIViewController, CLLocationManagerDelegate, UISearchBarDelegate, DataEnteredDelegate {


@IBOutlet weak var pincodeField: UITextField!
@IBOutlet weak var cityField: UITextField!
@IBOutlet weak var streetField: UITextField!
@IBOutlet weak var storeNoField: UITextField!
@IBOutlet weak var colonyField: UITextField!
@IBOutlet weak var landmarkField: UITextField!

@IBOutlet weak var mapView: MKMapView!
let annotation = MKPointAnnotation()

let locationManager = CLLocationManager()
var latitude: String?
var logitude: String?
override func viewDidLoad() {
    super.viewDidLoad()

    self.locationManager.requestAlwaysAuthorization()
    if CLLocationManager.locationServicesEnabled() {
        locationManager.delegate = self

        locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
        locationManager.startUpdatingLocation()
    }
}

override func viewWillAppear(_ animated: Bool) {
    self.navigationController?.navigationBar.isHidden=true;
    let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.triggerTouchAction(_:)))
    mapView.addGestureRecognizer(tapGesture)
}
@objc func triggerTouchAction(_ sender: UITapGestureRecognizer) {
    print("Please Help!")

    let viewController = self.storyboard?.instantiateViewController(withIdentifier: "NewZoomAddressViewController") as! NewZoomAddressViewController;
        viewController.delegate = self

    viewController.zipName = self.pincodeField.text
    viewController.sublocalityName = self.colonyField.text
    viewController.localityName = self.cityField.text
        self.navigationController?.pushViewController(viewController, animated: true);
}

func userDidEnterInformation(info: [String]) {
    print("zoom map address viewcontroller data \(info)")
}
@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[0] 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]
            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.streetField.text=placemarkDictonary["Street"] as? String
            self.colonyField.text=placemarkDictonary["SubLocality"] as? String
            self.landmarkField.text=placemarkDictonary["SubThoroughfare"] as? String
        }
    }

    let center = CLLocationCoordinate2D(latitude: userLocation.coordinate.latitude, longitude: userLocation.coordinate.longitude)
    let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
    mapView.setRegion(region, animated: true)
    // Drop a pin at user's Current Location
    let myAnnotation: MKPointAnnotation = MKPointAnnotation()
    myAnnotation.coordinate = CLLocationCoordinate2DMake(userLocation.coordinate.latitude, userLocation.coordinate.longitude);
    myAnnotation.title = "Current location"
    mapView.addAnnotation(myAnnotation)
    locationManager.stopUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
    switch status {
    case .notDetermined:
        print("User still thinking")
    case .denied:
        print("User hates you")
    case .authorizedWhenInUse:
        locationManager.stopUpdatingLocation()
    case .authorizedAlways:
        locationManager.startUpdatingLocation()
    case .restricted:
        print("User dislikes you")
    }
}
}

Next view controller code:

protocol DataEnteredDelegate: class {
func userDidEnterInformation(info: [String])
}
class NewZoomAddressViewController: UIViewController {
weak var delegate: DataEnteredDelegate? = nil
var userModel : ProfileModel?

var zipName: String?
var localityName: String?
var sublocalityName: String?

@IBOutlet weak var mapView: MKMapView!
@IBOutlet weak var addressLabel: UILabel!

override func viewDidLoad() {
    super.viewDidLoad()
    print("in Zoom map VC")
    mapView.delegate = self
    addressLabel.text = "\(self.sublocalityName!) \(localityName!) \(self.zipName!)"
}

@IBAction func confirmBtn(_ sender: Any) {
    delegate?.userDidEnterInformation(info: [zipName!,sublocalityName!, localityName!])
    self.navigationController?.popViewController(animated: true)
}

Solution

  • You were almost there. Just set the values to your textfields in your userDidEnterInformation(:) func:

    func userDidEnterInformation(info: [String]) {
       self.pincodeField.text = info[0]
       self.streetField.text = info[1]
       self.cityField.text = info[2]
    }
    

    However, accessing the String array subscripts with a number might lead to errors, I would suggest the following approach for you:

    1. You should define something like a model for your returned information rather than using a String Array. I suggest you add the following struct somewhere:
    struct DataEnteredModel {
       let pinCode: String
       let streetField: String
       let cityField: String
    }
    
    1. Change the function type in your delegate method from func userDidEnterInformation(info: [String]) to func userDidEnterInformation(info: DataEnteredModel)

    2. In confirmBtn(_:9, call the delegate function this way:

    @IBAction func confirmBtn(_ sender: Any) {
        guard
            let zipName = zipName,
            let sublocalityName = sublocalityName,
            let localityName = localityName 
            else { return }
        let enteredData = DataEnteredModel(pinCode: zipName, streetField: sublocalityName, cityField: localityName)
        delegate?.userDidEnterInformation(info: enteredData)
    }
    
    1. Finally, in your userDidEnterInformation method in ProfileAddressViewController you have to do:
    func userDidEnterInformation(info: DataEnteredModel) {
        self.pincodeField.text = info.pinCode
        self.streetField.text = info.streetField
        self.cityField.text = info.cityField
    }
    

    That should be it, in case of questions, feel free to ask!