Cole Roe Cole Roe - 3 months ago 20
Swift Question

UICollectionView Items not being reused properly (Swift 2.0+)

I have a UICollectionView inside of a TableView Cell. The CollectionView Cells themselves contain a UIImageView and a Label. The CollectionView Cells are supposed to display a users picture with their first name underneath. This data model is being structured within ViewDidLoad and has the correct data being output. However, my UICollectionViews are producing the user pictures and user names in erratic spots (i.e., user pictures and names are showing up on different TableView rows within the respective UICollectionViews of that different TableView row). I can try to elaborate on this more, if needed.

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

let cell = collectionView.dequeueReusableCellWithReuseIdentifier("userCell", forIndexPath: indexPath) as! wigoCollectionViewCell

var sumSections = 0
for i in 0 ..< indexPath.section {

let rowsInSection = eventFeed.numberOfRowsInSection(i)
sumSections = sumSections + rowsInSection

}
let currentRow = sumSections + indexPath.row

// Flip the collectionView
var scalingTransform : CGAffineTransform!
scalingTransform = CGAffineTransformMakeScale(-1, 1);
cell.transform = scalingTransform

// Make user profile picture circular and dispose of remaining image resources not visible
cell.userPicture.layer.cornerRadius = cell.userPicture.frame.size.width/2
cell.userPicture.clipsToBounds = true

for (key, value) in (sortedArray[currentRow]["usersJoining"]!! as? NSDictionary)! {

if key as? String != FIRAuth.auth()?.currentUser?.uid {

var name = String()
var photoUrl = NSURL()

name = value["userName"] as! String

let nameSplit = name.characters.split(" ").map(String.init)
// Edit label
cell.userNameLabel.text = nameSplit[0]

// Make UIImage = user picture
photoUrl = NSURL(string: value["userPhotoUrl"] as! String)!
let data = NSData(contentsOfURL: photoUrl)


cell.userPicture.image = UIImage(data: data!)

}

}

return cell

}


On printing any particular variables, the output is exactly what I want. So this is entirely a matter of displaying the correct information in the cells.

I am using
prepareForReuse
correctly to the best of my knowledge.

override func prepareForReuse() {

userPicture.image = nil
userNameLabel.text = ""

super.prepareForReuse()

}


The only solution I can think of revolves around using the
dispatch_async
methods to add the image in a background thread. However, I cannot seem to get that to solve my problem either.

I'm hoping someone here can help guide me with the correct method to solve my problem, as I haven't found any solutions through StackOverflow or the rest of the internet that solves my particular problem (or explains it very well for Swift 2.0+).

Thanks in advance.

Answer

I did, ultimately, discover the solution to my problem. So for anyone who is curious or has a similar problem:

The issue lied with iterating through an NSDictionary within the cellForItemAtIndexPath method. NSDictionaries are inherently unordered when created programmatically, and by iterating through the dictionary to get the data I needed resulted in it appearing as if there were load issues with the images in the cells within the CollectionView.

The solution was simply to mutate the NSDictionary into an Array and retrieve the values I needed from the array using indexPath.item as the index.

It's a very simple solution that simply didn't occur to me. So make sure your logic is solid if you're looking for a similar problem's solution as I was!

Comments