Bishan Bishan - 5 days ago 6
iOS Question

UICollectionView crashing after scroll and selecting cell

I have a

Horizontal CollectionView
which has cells with one
image view
inside. What i want to do is set a default selected cell. Selected cell should change its image color. And after if user select some other cell it should be selected and default selected cell should be deselected. Currently all of those are working. But sometimes when i'm scroll and selecting a cell its crashing saying as follow.


ERROR: unexpectedly found nil while unwrapping an Optional value


Here is my complete code

override func viewDidLoad() {
super.viewDidLoad()
self.collectionView.delegate = self
self.locationManager.delegate = self
collectionView.allowsMultipleSelection = false
}

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


func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {

let cell = collectionView.cellForItemAtIndexPath(indexPath) as! CategoryCell
cell.CarImage.image = UIImage(named: CatImages[indexPath.row])?.maskWithColor(UIColorFromRGB(0xEA7C6A))
cell.Name.textColor = UIColorFromRGB(0xEA7C6A)

}

func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {

let cell = collectionView.cellForItemAtIndexPath(indexPath) as! CategoryCell
cell.CarImage.image = UIImage(named: CatImages[indexPath.row])
cell.Name.textColor = UIColor.darkGrayColor()

}

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! CategoryCell

cell.Name.text = CatNames[indexPath.row]


// setup selectedBackgroundView
if(cell.selected == true){
cell.CarImage.image = UIImage(named: CatImages[indexPath.row])!.maskWithColor(UIColorFromRGB(0xEA7C6A))
cell.Name.textColor = UIColorFromRGB(0xEA7C6A)
}
else{
cell.CarImage.image = UIImage(named: CatImages[indexPath.row])
cell.Name.textColor = UIColor.darkGrayColor()
}


return cell
}


override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
let indexPath = NSIndexPath(forRow: 0, inSection: 0)
self.collectionView.selectItemAtIndexPath(indexPath, animated: false, scrollPosition: .None)
}

extension UIImage {
func maskWithColor(color: UIColor) -> UIImage? {

let maskImage = self.CGImage
let width = self.size.width
let height = self.size.height
let bounds = CGRectMake(0, 0, width, height)

let colorSpace = CGColorSpaceCreateDeviceRGB()
let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.PremultipliedLast.rawValue)
let bitmapContext = CGBitmapContextCreate(nil, Int(width), Int(height), 8, 0, colorSpace, bitmapInfo.rawValue) //needs rawValue of bitmapInfo

CGContextClipToMask(bitmapContext, bounds, maskImage)
CGContextSetFillColorWithColor(bitmapContext, color.CGColor)
CGContextFillRect(bitmapContext, bounds)

//is it nil?
if let cImage = CGBitmapContextCreateImage(bitmapContext) {
let coloredImage = UIImage(CGImage: cImage)

return coloredImage

} else {
return nil
}
}
}

Answer
     func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
            guard collectionView.cellForItemAtIndexPath(indexPath) != nil else {
                  return
            }
            let cell = collectionView.cellForItemAtIndexPath(indexPath) as! CategoryCell
            cell.CarImage.image = UIImage(named: CatImages[indexPath.row])?.maskWithColor(UIColorFromRGB(0xEA7C6A))
            cell.Name.textColor = UIColorFromRGB(0xEA7C6A)

    }

    func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
            guard collectionView.cellForItemAtIndexPath(indexPath) != nil else {
                  return
            }
            let cell = collectionView.cellForItemAtIndexPath(indexPath) as! CategoryCell
            cell.CarImage.image = UIImage(named: CatImages[indexPath.row])
            cell.Name.textColor = UIColor.darkGrayColor()

    }

This basically answers your question because on this part of your code

   let cell = collectionView.cellForItemAtIndexPath(indexPath) as! CategoryCell

You're basically hard casting it using as! and the app will crash if the value of collectionView.cellForItemAtIndexPath(indexPath) is nil

Alternatively you can also use the if let syntax instead of guard else

if let cell = collectionView.cellForItemAtIndexPath(indexPath) {
    let aCell = cell as! CategoryCell
    // do stuff here
}
Comments