2

I have successfully populated a UICollectionView controller with data and images from a CloudKit record, however I am having a problem passing the selected cell to the details UIViewController. Here is my code thus far -

override func numberOfSections(in collectionView: UICollectionView) -> Int {
    return 1
}


override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return self.staffArray.count

}

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> StaffCVCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! StaffCVCell

    let staff: CKRecord = staffArray[indexPath.row]

    let iconImage = staff.object(forKey: "staffIconImage") as? CKAsset
    let iconData : NSData? = NSData(contentsOf:(iconImage?.fileURL)!)


    let leaderNameCell = staff.value(forKey: "staffName") as? String
    cell.leaderNameLabel?.text = leaderNameCell

    cell.leaderImageView?.image = UIImage(data:iconData! as Data);
    return cell 
}


func prepare(for segue: UIStoryboardSegue, sender: StaffCVCell) {
    if segue.identifier == "showStaffDetail" {
        let destinationController = segue.destination as! StaffDetailsVC
        if let indexPath = collectionView?.indexPath {
            let staffLeader: CKRecord = staffArray[indexPath.row]
            let staffID = staffLeader.recordID.recordName
            destinationController.staffID = staffID
        }
    }
}

The problem occurs at the line -

let staffLeader: CKRecord = staffArray[indexPath.row]

where I am presented with the error -

Value of type '(UICollectionViewCell) -> IndexPath?' has no member 'row'

I have tried replacing row with cell, however this only presents another error -

Value of type '(UICollectionViewCell) -> IndexPath?' has no member 'cell'

I am sure there is something fundamental i'm missing but cannot see it. Any pointers greatly appreciated.

Bowcaps
  • 127
  • 2
  • 11
  • A collection view doesn't have an `indexPath` property. You might mean `collectionView?.indexPathsForSelectedItems?.first`? – dan Mar 15 '17 at 16:23
  • Thanks dan, however that changes my problem a little, now I have collected the first record at the selected indexPath, how do I then use that to make the next line work `let staffLeader: CKRecord = staffArray[indexPath]` i.e. collect all the data from the CKRecord for that item and then pass the recordID in the segue? – Bowcaps Mar 15 '17 at 17:06
  • A little further on now - I have changed the prepareForSegue func to - ` override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "showStaffDetail" { let destinationController = segue.destination as! StaffDetailsVC if let indexPath = collectionView?.indexPathsForSelectedItems?.first { let staff: CKRecord = staffArray[indexPath.item] let staffID = staff.recordID.recordName destinationController.staffID = staffID } } }` – Bowcaps Mar 15 '17 at 19:48
  • And now receive the following error - `Could not cast value of type 'UIViewController' (0x1089b0758) to 'MedTRiM.StaffDetailsVC' (0x104820678)` when selecting a cell – Bowcaps Mar 15 '17 at 19:49

1 Answers1

2

If your segue is triggered by touching a cell, you want something along the lines of code below:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

    if segue.identifier == "showStaffDetail" {

        let destinationController = segue.destination as! StaffDetailsVC

        // Find the correct indexPath for the cell that triggered the segue
        // And check that the sender is, in fact, a StaffCVCell
        if let indexPath = collectionView?.indexPath(for: sender), let sender = sender as? StaffCVCell {

            // Get your CKRecord information
            let staffLeader: CKRecord = staffArray[indexPath.item]
            let staffID = staffLeader.recordID.recordName

            // Set any properties needed on your destination view controller
            destinationController.staffID = staffID
        }
    }
}

Note that I've changed the method signature back to the standard method signature.

Robotic Cat
  • 5,899
  • 4
  • 41
  • 58
  • There seems to be an issue with this line - `let destinationController = segue.destination as! StaffDetailsVC` as the following error occurs - `Could not cast value of type 'UIViewController' (0x110b08758) to 'StaffDetailsVC' (0x10cb1d678)` ? – Bowcaps Mar 15 '17 at 23:31
  • @Bowcaps: I took `StaffDetailsVC` from *your* code. This should be the name of the class of your destination view controller - replace it with the correct name and make sure the correct class is set for that View Controller in the Storyboard. – Robotic Cat Mar 16 '17 at 00:47
  • That's my confusion, StaffDetailsVC is the destination UIViewController, with regard the correct class, should it be a UIViewController (which it currently is) or something else? Thank you for the ongoing advice. – Bowcaps Mar 16 '17 at 09:35
  • It should definitely be a subclass of UIViewController. The error message means that you have a problem in your Storyboard (probably). See this answer for the probable to solution this new issue: http://stackoverflow.com/q/31440964/558933 – Robotic Cat Mar 16 '17 at 09:52
  • I figured out, like you, it may be SB related, I deleted the VC from the storyboard, recreated it, hooked it up and it worked first time. I'm not sure what the actual fault was, but I did have a crash in Xcode yesterday, so that could have possible been a contributory factor? Thanks again for your assistance with this. – Bowcaps Mar 16 '17 at 10:27