draw(_ rect:CGRect)未在自定义视图中调用

时间:2018-02-10 21:19:42

标签: ios swift

我正在尝试通过扩展类UIView来创建自定义视图,该类可以在自定义视图的中心显示一个圆圈。 为了添加自定义绘图,我重写了draw(_ rect:CGRect)方法,如下所示。

    public override func draw(_ rect: CGRect) {
        super.draw(rect)
        let center = CGPoint(x: bounds.width / 2, y: bounds.height / 2)
        let minLength = bounds.width <= bounds.height ? bounds.width : bounds.height
        let circlePath = UIBezierPath (arcCenter: center, radius: CGFloat(minLength  / 2), startAngle: 0, endAngle: CGFloat(Float(360).degreesToRadians) , clockwise: true)

        let shapeLayer = CAShapeLayer()
        shapeLayer.path = circlePath.cgPath
        shapeLayer.fillColor = circleColor.cgColor
        layer.addSublayer(shapeLayer)
    }

但是当我尝试在storyboard中添加相同的自定义组件并在draw方法中添加断点时,它没有被调用。为了好奇,我在init中添加了一个断点?(编码器aDecoder:NSCoder)方法被调用。此外,当我尝试覆盖下面的方法时,它工作正常。

required public init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    drawCircle()
}

fileprivate func drawCircle() {
    let center = CGPoint(x: bounds.width / 2, y: bounds.height / 2)
    let minLength = bounds.width <= bounds.height ? bounds.width : bounds.height
    let circlePath = UIBezierPath (arcCenter: center, radius: CGFloat(minLength  / 2), startAngle: 0, endAngle: CGFloat(Float(360).degreesToRadians) , clockwise: true)

    let shapeLayer = CAShapeLayer()
    shapeLayer.path = circlePath.cgPath
    shapeLayer.fillColor = circleColor.cgColor

    layer.addSublayer(shapeLayer)
}

方法的问题是我有一个自定义属性circleColor

@IBInspectable
public var circleColor : UIColor = UIColor.gray
调用init方法时尚未设置的

,它总是绘制一个灰色圆圈。

请帮助告诉我没有调用draw方法的原因。

提前致谢

1 个答案:

答案 0 :(得分:2)

我不确定你的根本错误在哪里,但你不应该只是添加一个图层来覆盖draw(:)。这意味着每次组件重新渲染时都会再次添加新图层。那不是你想要的。

更改颜色属性时,还应确保更新图层颜色。为此,只需保存对图层的引用:

private let shapeLayer = CAShapeLayer()

@IBInspectable
public var circleColor : UIColor = UIColor.gray  {
   didSet {
      shapeLayer.fillColor = circleColor.cgColor
   }
}

public override init(frame: CGRect = .zero) {
    super.init(frame: frame)
    updateLayer()
    layer.addSublayer(shapeLayer)
}

required public init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    updateLayer()
    layer.addSublayer(shapeLayer)
}

fileprivate func updateLayer() {
    let center = CGPoint(x: bounds.width / 2, y: bounds.height / 2)
    let minLength = min(bounds.width, bounds.height)
    let circlePath = UIBezierPath(arcCenter: center, radius: minLength / 2, startAngle: 0, endAngle: CGFloat(Float(360).degreesToRadians), clockwise: true)

    shapeLayer.path = circlePath.cgPath
    shapeLayer.fillColor = circleColor.cgColor
}

override func layoutSubviews() {
    super.layoutSubviews()
    // update layer position
    updateLayer()
}

如果您真的想要覆盖draw(rect:),则根本不需要创建图层或覆盖初始值设定项:

@IBInspectable
public var circleColor : UIColor = UIColor.gray  {
   didSet {
      setNeedsDisplay()
   }
}

public override func draw(_ rect: CGRect) {
    // no need to call super.draw(rect)

    let center = CGPoint(x: bounds.width / 2, y: bounds.height / 2)
    let minLength = min(bounds.width, bounds.height)
    let circlePath = UIBezierPath(arcCenter: center, radius: minLength / 2, startAngle: 0, endAngle: .pi * 2, clockwise: true)

    // the following methods use current CGContext
    circleColor.set()
    circlePath.fill()
}