I have a custom collection view cell that is adding a dashed border to the cell layer with the following code:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = appDealCollectionView.dequeueReusableCell(withReuseIdentifier: "appDealCollectionCell", for: indexPath) as! AppDealCollectionViewCell
if let codes = discountCodes {
cell.discountCodeTitle.text = codes[indexPath.row].codeMessageOne
cell.discountCode.text = codes[indexPath.row].code
let yourViewBorder = CAShapeLayer()
yourViewBorder.strokeColor = UIColor.black.cgColor
yourViewBorder.lineWidth = 2
yourViewBorder.lineDashPattern = [10, 10]
yourViewBorder.frame = cell.bounds
yourViewBorder.fillColor = nil
yourViewBorder.path = UIBezierPath(roundedRect: cell.bounds, cornerRadius: 6).cgPath
cell.layer.addSublayer(yourViewBorder)
}
return cell
}
This code works perfectly fine on the initial loading of the view. However, when the orientation changes, the cell size changes. The above code does correctly draw the new border CAShapeLayer, but the previously drawn border layer is still present which were drawn based on the old size.
The result is two different border layers being present at the same time overlapping each other with different dimensions.
How do I invalidate any previously drawn CAShapeLayers? Where is the invalidation done? In cellForItemAt? Or possibly inside the custom "AppDealCollectionViewCell" itself?
Since cells are reusable, every call of cellForRowAtIndexPath
will add another instance of CAShapeLayer
onto cell. That is why you are having several borders overlapping each other. Also CALayer
doest not support neither auto layout nor autoresizingMask
, so you have to update size of your CAShapeLayer
manually.
You should create subclass of UITableViewCell
, then create instance of CAShapeLayer
and store pointer to it in class property variable. Once layout cycle occurs, in layoutSubviews
function you need to update frame of CAShapeLayer
.
The final implementation looks like that:
class BorderedTableViewCell: UITableViewCell {
lazy var borderLayer = CAShapeLayer()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setupBorderLayer()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupBorderLayer()
}
private func setupBorderLayer() {
borderLayer.strokeColor = UIColor.black.cgColor
borderLayer.lineWidth = 2
borderLayer.fillColor = nil
borderLayer.lineDashPattern = [10, 10]
layer.addSublayer(borderLayer)
}
private func updateBorderLayer() {
borderLayer.frame = bounds
borderLayer.path = UIBezierPath(roundedRect: bounds, cornerRadius: 6).cgPath
}
override func layoutSubviews() {
super.layoutSubviews()
updateBorderLayer()
}
}
I hope this helps.