解除意外行为

时间:2018-04-12 13:14:21

标签: ios swift unwind-segue

我在项目中传递了展开数据的问题。 正如我在dfri中看到的那样在这篇文章中回答Passing data with unwind segue 它工作得很好,我打印的变量保持它们以正确的顺序打印的值,第一个是传递的变量,第二个是传递的变量。第二次从展开功能打印。 当我以与上述示例相同的方式实现展开功能时,我得到完全不同的顺序o变量打印。 在我的例子中,我首先从unwind函数获得打印,然后从CollectionView didSelect函数获得打印。 并且应该接收数据的变量保持为零。 我还尝试将值赋给静态var并使用它但不改变它。 这是两个ViewControllers代码:

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)

}
}

1 个答案:

答案 0 :(得分:1)

正如您所发现的,当您直接从collectionView单元格中连接segue时,segue会在didSelectItemAt运行之前运行。

有几种方法可以解决这个问题。一种是跳过使用didSelectItemAt并在prepare(for:sender)中完成所有工作。

在这种情况下,sender是collectionView单元格,因此使用它来获取indexPath,然后设置数据:

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]
    }
}

注意:您应该为您的展开segue提供一个标识符(例如"unwindToCaller")并检查它。您可以在文档大纲视图中找到segue,并在Xcode右侧的 Attributes Inspector 中设置标识符。

然后你会这样检查:

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

}

替代解决方案:

  1. 不是从collectionView单元连接你的segue,而是从collectionViewController顶部的viewController图标连接它。为segue指定一个标识符,例如"returnToCaller"
  2. didSelectItemAt中,在设置数据值后调用segue:

    self.performSegue(withIdentifier: "returnToCaller", sender: self)