Search code examples
iosswiftxcodeuitableviewmask

Crash when scrolling a UITableView after applying mask to an image


I am applying a mask to an image in a custom table cell. The mask works correctly but as soon as I scroll the table I get a Fatal error: Unexpectedly found nil while unwrapping an Optional value on the mask UIImageView.

Here is my code (I've ommitted some variable declarations for brevity):

  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "LeagueTableCell") as UITableViewCell?
    
    let badgeFgr = cell?.viewWithTag(9) as! UIImageView
    let badgeMask = cell?.viewWithTag(4) as! UIImageView

    // Set the image
    if let theImage = UIImage(named: imageString) {
      badgeFgr.image = theImage.withRenderingMode(.alwaysTemplate)
      badgeFgr.tintColor = fgrCol
        
      // Apply the mask
      badgeMask.image = UIImage(named: "maskShape")
      badgeFgr.mask = badgeMask
    }

    return cell!
  }

When I scroll the table the app crashes and the Fatal error: Unexpectedly found nil while unwrapping an Optional value occurs on this line:

    let badgeMask = cell?.viewWithTag(4) as! UIImageView

When I show the image without applying the mask (by removing the lines below) it shows the image without masking and it doesn't crash when scrolling:

    // Apply the mask
    theMask.image = UIImage(named: "maskShape")
    theImage.mask = theMask

So what is the correct way to apply a mask to an image in a custom tableview cell?


Solution

  • The reason you are getting the error is because this line:

    badgeFgr.mask = badgeMask
    

    removes that image view.

    Instead of trying to use a pre-added image view in your cell prototype, apply the mask like this:

    // Apply the mask
    if let maskImg = UIImage(named: "maskShape") {
        // create a NEW image view to use as the mask
        let imgV = UIImageView(frame: badgeFgr.bounds)
        imgV.image = maskImg
        badgeFgr.mask = imgV
    }