Reputation: 537
I have a UICollectionViewCell:
"Gradient View" is a UIView that has a gradient:
Source of data is CoreData. On Collection view, I have buttons that sort CoreData:
@IBAction func allMealsBtn(_ sender: Any) {
let fetchRequest: NSFetchRequest<Meal> = Meal.fetchRequest()
let dateSort = NSSortDescriptor(key: "created", ascending: false)
fetchRequest.sortDescriptors = [dateSort]
let controller = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
controller.delegate = self
self.controller = controller
do {
try controller.performFetch()
} catch {
let error = error as NSError
print("Couldn't fetch data from CoreData with error: \(error.debugDescription)")
}
collectionView.reloadData()
}
After pressing the sort button, collection view reloads and displays the right data. However, the Gradient View multiplies, as though the cell wasn't destroyed. Here what I see after sorting data multiple times:
How to make sure that my cell is redrawn from scratch?
Edit:
My custom cell class. So in configureCell I have to check if my gradientView is added to the view, if yes, then add gradient, if not, add it, and add gradient. How can I do this check?
class CollectionCell: UICollectionViewCell {
@IBOutlet weak var mealImg: UIImageView!
@IBOutlet weak var mealTitleLbl: UILabel!
@IBOutlet weak var gradientView: UIView!
func configureCell(meal: Meal) {
mealTitleLbl.text = meal.title
let img = meal.getMealImage()
mealImg.image = img
gradientView.addGradientWithColor(color: UIColor.clear)
// How can I check if my gradientView is added to the view, if yes, then add gradient, if not, add it, and only then add gradient.
}
override func prepareForReuse() {
super.prepareForReuse()
gradientView.removeFromSuperview()
}
}
extension UIView {
func addGradientWithColor(color: UIColor) {
let gradient = CAGradientLayer()
gradient.frame = self.bounds
let topColor = UIColor(red:0.07, green:0.07, blue:0.07, alpha:1)
gradient.colors = [topColor.cgColor, color.cgColor]
self.layer.insertSublayer(gradient, at: 0)
}
}
Edit: I've dropped the extension and implemented the flag logic. However, after the view gets removed, it never reappears on the cell after performing the search. Any thoughts?
class CollectionCell: UICollectionViewCell {
@IBOutlet weak var mealImg: UIImageView!
@IBOutlet weak var mealTitleLbl: UILabel!
@IBOutlet weak var gradientView: UIView!
var isGradientAdded = false
func configureCell(meal: Meal) {
mealTitleLbl.text = meal.title
let img = meal.getMealImage()
mealImg.image = img
if isGradientAdded == false {
addGradient()
isGradientAdded = true
}
}
override func prepareForReuse() {
super.prepareForReuse()
gradientView.removeFromSuperview()
}
func addGradient () {
let gradient = CAGradientLayer()
gradient.frame = gradientView.bounds
let topColor = UIColor(red:0.07, green:0.07, blue:0.07, alpha:1)
let botomColor = UIColor.clear
gradient.colors = [topColor.cgColor, botomColor.cgColor]
gradientView.layer.insertSublayer(gradient, at: 0)
}
}
Upvotes: 0
Views: 686
Reputation: 9612
In UICollectionViewCell
subclass (Cell) you should override prepeareForReuse
function - to turn cell to default mode.
If you don't have the custom class for Cell
- create it before and assign in interface builder as class for your Cell
cell (and of course don't forget about outlets)
override func prepareForReuse() {
super.prepareForReuse()
//set cell to initial state here
//e.g try to remove you gradient view
yourGradientView.removeFromSuperview()
}
Upvotes: 2