Search code examples
swiftuicollectionviewuicollectionviewcellswift2

Segue from a UICollectionView in Swift


This question probably has an extremely simple answer, but I can't get my head around it. Nor can I find a particularly useful answer that works anywhere online.

I simply can't get a segue working from a UICollectionViewCell. I'm possibly coming at it from the wrong angle, as I assumed it worked in a very similar way to a table view segue. Working on that premise, if I was using a table view, it would look something like this:

if segue.identifier == "TripsToPastTripDetailsSegue" {
        let newViewController = segue.destinationViewController as! pastTripDetailViewController
        let selectedRow: NSManagedObject = tripsList[tableView.indexPathForSelectedRow!.row] as NSManagedObject
        newViewController.passedTrip = selectedRow as! Trips   
    }

So, with the table view I would be passing a single object (from Core Data) over to the another view controller. Simple. But I just can't translate that over to a collection view.

I have been attempting something along these lines:

if segue.identifier == "pastTripCollectionToSavedLocationSegue" {
        let newViewController = segue.destinationViewController as! pastTripDetailViewController
        let selectedRow: NSManagedObject = locationsList[collectionView.indexPathForCell(pastLocationImageCollectionViewCell)] as! NSManagedObject
        newViewController.passedTrip = selectedRow as! Trips   
    }

But this gives me an error of Cannot find member 'indexPathForCell', so I'm obviously doing something very wrong. This is one of many errors I've had whilst playing around with the code.

Can someone point me in the right direction?

EDIT:

As requested by @Laffen, the UICollectionView appears in the following locations in the code:

class pastTripDetailViewController: UIViewController,  UICollectionViewDataSource, UICollectionViewDelegate, MKMapViewDelegate {

As an IBOutlet:

@IBOutlet weak var collectionView: UICollectionView!

Data source and delegate in ViewDidLoad:

self.collectionView.dataSource = self
self.collectionView.delegate = self

And here's the rest:

func collectionView(collectionView: UICollectionView, numberOfSectionsInCollectionView indexPath: Int) -> Int {
    return 1
}

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

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

    let location = self.locationsList[indexPath.row]
    let cell: pastLocationImageCollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier("imageCell", forIndexPath: indexPath) as! pastLocationImageCollectionViewCell
    cell.locationImage.image = UIImage(data: location.image!)

    return cell
}

func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
    performSegueWithIdentifier("pastTripCollectionToSavedLocationSegue", sender: self)
}

Solution

  • Maybe this could work for you:

    let indexPath: NSIndexPath = self.collectionView.indexPathsForSelectedItems().first!
    let selectedRow: NSManagedObject = locationsList[indexPath] as! NSManagedObject
    

    This will only work if the locationsList is of type dictionary and is initialized like this:

    var locationsList = [NSIndexPath: NSManagedObject]()
    

    Hope this is helpful

    Edit:

    It seems you are trying to pass along the pastLocationImageCollectionViewCell type in the indexPathForCell. The argument must be an instance of the type pastLocationImageCollectionViewCell.

    Try this:

    Edited: example below will only work as desired when having only one section in the UICollectionView.

    func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "pastTripCollectionToSavedLocationSegue" {
            let newViewController = segue.destinationViewController as! pastTripDetailViewController
            let indexPath = sender as! NSIndexPath
            let selectedRow: NSManagedObject = locationsList[indexPath.row] as! NSManagedObject
            newViewController.passedTrip = selectedRow as! Trips   
        }
    }
    
    // Set the indexPath of the selected item as the sender for the segue
    func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
        performSegueWithIdentifier("pastTripCollectionToSavedLocationSegue", sender: indexPath)
    }