0

I'm having a problem with the unwind data passing in my project. as I saw in dfri answer in this post Passing data with unwind segue it works perfectly and I print the variables that hold value they get printed in the right order, 1st the variable to pass and 2nd the passed variable. 2nd get printed from the unwind function. As I implement the unwind function in the same way as the above mentioned example I get totally different order o variables prints. In my case I get first the print from the unwind function and second the print from the CollectionView didSelect function. and the variable that should receive the data stays nil. I also tried to assign value to a static var and use that but no changes to that either. here's the two ViewControllers code:

import UIKit import MapKit

class MapViewController: UIViewController, MKMapViewDelegate {

@IBOutlet weak var mapView: MKMapView!

@IBOutlet weak var dropPinButton: UIButton!

@IBOutlet weak var centerMApButton: UIButton!

var pin: AnnotationPinn!




var dataReceived: String? 

override func viewDidLoad() {
    super.viewDidLoad()
    mapView.delegate = self

    // variables that hold values for selected icon, to be used for displaying the pin



    let latitude: Double = 44.498955
    let longitude: Double = 11.327591

    let coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)

    let region = MKCoordinateRegionMakeWithDistance(coordinate, 1000, 1000)

    mapView.setRegion(region, animated: true)

    // title may be to be taken from iconNames[indexpath.row]
    pin = AnnotationPinn(title: "strada chiusa", subtitle: "", coordinate: coordinate)


}





//custom pin image , named: iconsImages[indexPath.row]
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
    let annotationView = MKAnnotationView(annotation: pin, reuseIdentifier: "strada chiusa")

    annotationView.image = UIImage(named: "\(String(describing: dataReceived))") // here choose the image to load //        annotationView.image = UIImage(named: "\(String(describing: MyVariables.dataReceived))") // here choose the image to load
     //        annotationView.image = UIImage(iconsNames[1])

    let transform = CGAffineTransform(scaleX: 0.5, y: 0.5)
    annotationView.transform = transform

    return annotationView
}


func dropPin() { //           print("3\(String(describing: dataReceived))")
    mapView.addAnnotation(pin)
}



@IBAction func dropPinButton(_ sender: Any) {

    performSegue(withIdentifier: "chooseIconSegue", sender: self)


}


@IBAction func unwindHere(sender:UIStoryboardSegue) { // datas coming back


    if let sourceViewController = sender.source as? IconsViewController { //            MyVariables.dataReceived = sourceViewController.dataPassed
        dataReceived = sourceViewController.dataPassed //            print(MyVariables.dataReceived!)

        print("3\(String(describing: dataReceived))")
        dropPin()


    }

}

 }

vc2

import UIKit

class IconsViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {

var dataPassed: String?

@IBOutlet weak var iconsCollectionView: UICollectionView!
override func viewDidLoad() {
    super.viewDidLoad()


}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}
var iconsNames = ["lavori in corso", "ciclabile chiusa", "strada chiusa", "bici rubata", "bici sospetta" ]
var iconsImages = [UIImage(named: "lavori in corso"), UIImage(named: "ciclabile chiusa"), UIImage(named: "strada chiusa"), UIImage(named: "bici rubata"), UIImage(named: "bici sospetta")]

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return iconsNames.count
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "iconCell", for: indexPath as IndexPath) as! IconsCollectionViewCell

    cell.iconImage?.image = self.iconsImages[indexPath.row]
    cell.iconLabel?.text = iconsNames[indexPath.row]
    // MyVariables.dataReceived = iconsNames[indexPath.row]

    return cell
}


func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

    dataPassed = iconsNames[indexPath.row]
    MyVariables.dataReceived = dataPassed

      print ("2\(iconsNames[indexPath.row])")
    print("1\(dataPassed!)")
  //        navigationController?.popViewController(animated: true) // //        dismiss(animated: true, completion: nil)

}
}
Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Vinny Twice
  • 41
  • 1
  • 9
  • @Ankit Jayaswal thank you for the edit, I did it a few times but didn't well. I guess it's because of Safari. Any idea about my problem? – Vinny Twice Apr 12 '18 at 13:23

1 Answers1

1

As you've discovered, when you wire the segue directly from the collectionView cell, the segue runs before didSelectItemAt runs.

There are a couple of way of dealing with that. One is to skip using didSelectItemAt and do all of your work in prepare(for:sender).

The sender in this case is the collectionView cell, so use that to get the indexPath and then set your data:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let cell = sender as? UICollectionViewCell,
        let indexPath = self.iconsCollectionView.indexPath(for: cell) {
            self.dataPassed = iconsNames[indexPath.row]
    }
}

Note: You should give your unwind segue an identifier (such as "unwindToCaller") and check that as well. You can find the segue in the Document Outline view, and set the identifier in the Attributes Inspector on the right of Xcode.

Then you'd check like this:

if segue.identifier == "unwindToCaller" {
    if let cell = sender as? ...

}

Alternate solution:

  1. Instead of wiring your segue from the collectionView cell, wire it from the viewController icon at the top of the collectionViewController. Give the segue an identifier such as "returnToCaller".
  2. In didSelectItemAt, call the segue after you have set the data value:

    self.performSegue(withIdentifier: "returnToCaller", sender: self)
    
vacawama
  • 150,663
  • 30
  • 266
  • 294
  • I did give the unwind segue an identifier and insert this code in the IconsCollectionView `override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "unwindHereSegue" { if let cell = sender as? UICollectionViewCell, let indexPath = self.collectionView?.indexPath(for: cell) { self.dataPassed = iconsNames[indexPath.row] } } }` but got this error `Ambiguous reference to member 'collectionView(_:number` at self. of `let indexPath = self.collectionView?.indexPath(for: cell) ` – Vinny Twice Apr 12 '18 at 14:01
  • Sorry about that. Fixed. It should be `let indexPath = self.iconsCollectionView.indexPath(for: cell)`. – vacawama Apr 12 '18 at 14:06
  • 2nd solution worked !! thank you, I'll give a try to the 1st solution as well again . – Vinny Twice Apr 12 '18 at 14:13
  • now get the value back to MapViewController, but still doesn't get used to display the right image in ` annotationView.image = UIImage(named: "\(String(describing: dataReceived))")` .. If I instead put an image name directly than it does display it when the drop pin button get tapped – Vinny Twice Apr 12 '18 at 14:26
  • Use `annotationView.image = UIImage(named: dataReceived!)` – vacawama Apr 12 '18 at 14:29
  • 1
    I swear I did try it before, but I guess I didn't force unwrap.. anyway completely solved! many thanks again. – Vinny Twice Apr 12 '18 at 14:44