Reputation: 17591
I am trying to set this custom view in every single row of my tableview.
In my interface builder I add a UIView in the UITableViewCell and I link the IBOutlet. So I subclass it to CircleView
this is its class
class CircleView: UIView {
var shapeLayer = CAShapeLayer()
override func draw(_ rect: CGRect) {
super.draw(rect)
let circlePath = UIBezierPath(arcCenter: CGPoint(x: rect.width/2,y: rect.height/2), radius: CGFloat(20), startAngle: CGFloat(0), endAngle:CGFloat(Double.pi*2), clockwise: true)
shapeLayer.path = circlePath.cgPath
shapeLayer.fillColor = Constants.defaultCircleFillColor
shapeLayer.strokeColor = UIColor.clear.cgColor
shapeLayer.lineWidth = 1.5
self.layer.addSublayer(shapeLayer)
}
func setColor(_ color: UIColor) {
shapeLayer.strokeColor = color.cgColor
}
}
but when I try to call the setColor
func in cellForRowAt
delegate, nothing happen.
Is there a way to manage its stroke color?
this is the cellForRowAt
:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let remote_row: RemoteType = sections[indexPath.section].cellData[indexPath.row]
if let cell = tableView.dequeueReusableCell(withIdentifier: remote_row.identifier) as? RemoteCell {
switch remote_row {
case .Item(circleColor: let color, text: let title):
cell.configCell(circleColor: color, description: title)
}
return cell
} else {
fatalError("Unknown identifier")
}
}
and the RemoteCell:
class RemoteCell: UITableViewCell {
@IBOutlet weak var title: UILabel!
@IBOutlet weak var circleView: CircleView!
@IBOutlet weak var settingButton: UIButton!
func configCell(circleColor: UIColor, description: String) {
title.text = description
circleView.setColor(UIColor.blue)
}
}
Upvotes: 0
Views: 108
Reputation: 1326
the draw method is going to get executed when your tableView draws the cell, so the color change is going to get overriden and set to clear.
try something like this:
class CircleView: UIView {
var shapeLayer = CAShapeLayer()
var myColor:UIColor = UIColor.clear
override func draw(_ rect: CGRect) {
let circlePath = UIBezierPath(arcCenter: CGPoint(x: rect.midX, y: rect.midY), radius: 20, startAngle: 0, endAngle:(.pi * 2), clockwise: true)
shapeLayer.path = circlePath.cgPath
shapeLayer.fillColor = Constants.defaultCircleFillColor
shapeLayer.strokeColor = myColor.cgColor
shapeLayer.lineWidth = 1.5
self.layer.addSublayer(shapeLayer)
}
func setColor(_ color: UIColor) {
myColor = color
// shapeLayer.strokeColor = color.cgColor
}
}
Upvotes: 1
Reputation: 54775
As you have stated in comments, by setting up breakpoints, you realised that setColor
is called before draw
would be called. This is expected behaviour due to the drawing cycle of UIView
.
As the UIView documentation states in the The View Drawing Cycle part,
View drawing occurs on an as-needed basis. When a view is first shown, or when all or part of it becomes visible due to layout changes, the system asks the view to draw its contents. For views that contain custom content using UIKit or Core Graphics, the system calls the view’s draw(_:) method.
This means that in cellForRowAt
the draw
method is not yet called, since the cell itself is not even returned and not displayed on the screen. You could fix this issue, by setting up a new instance variable for your CircleView
class, that stores the colour you want to use in setColor
and use this colour directly in the draw
method. In cellForRowAt
just assign the colour you used as an input to setColor
before to this new instance property and the issue should be fixed.
Upvotes: 1