Swift 函数未在更新视图中绘制圆

Swift function not drawing circle in updated view

我的 View Controller 中有一个步进器,用于更新我的 UIView 中的变量(redd1greenn1bluee1)。 drawRect 绘制一个初始圆圈,updateColor 用于在其上绘制一个颜色更新的新圆圈。当我调用 updateColor 时变量会更新,我知道它们会通过,因为当我在 updateColor 中打印出它们的值时,它们是正确的。 updateColor 不会画新的圆。

class UIView1: UIView {

    var redd1 = 0.0;
    var greenn1 = 0.0;
    var bluee1 = 0.0;

    override init(frame: CGRect)
    {
        super.init(frame: frame)
    }
    required init?(coder aDecoder: NSCoder)
    {
        super.init(coder: aDecoder)
    }

    override func drawRect(rect: CGRect)
    {
        let circle2 = UIView(frame: CGRect(x: -25.0, y: 10.0, width: 100.0, height:100.0))
        circle2.layer.cornerRadius = 50.0
        let startingColor2 = UIColor(red: (CGFloat(redd1))/255, green: (CGFloat (greenn1))/255, blue: (CGFloat(bluee1))/255, alpha: 1.0)
        circle2.backgroundColor = startingColor2;
        addSubview(circle2);
    }

    func updateColor()
    {
        let circle = UIView(frame: CGRect(x: -25.0, y: 10.0, width: 100.0, height: 100.0))
        circle.layer.cornerRadius = 50.0;
        let startingColor = UIColor(red: (CGFloat(redd1))/255, green: (CGFloat(greenn1))/255, blue: (CGFloat(bluee1))/255, alpha: 1.0)
        circle.backgroundColor = startingColor;
        addSubview(circle);   
    }   
}

正如你所提到的,两者都有它们应有的价值。 根据您的代码片段,您绘制的两个圆圈完全位于同一位置,并且颜色完全相同。他们应该如何区分?当然,当它们具有相同的颜色和相同的位置时,您看不到这两个圆圈。它们被覆盖了。

不要在 drawRect 中调用 addSubview。仅当您要自己画圆时才使用 drawRect(例如,通过调用 UIBezierPathstroke)。或者,如果您要将圆圈添加为子视图(作为视图 layerCAShapeLayer 子层),则完全退出 drawRect

但是通过在 updateColor 中调用 addSubview,您并没有改变颜色,而是每次都添加了另一个子视图。同样,通过在 drawRect 中调用 addSubview,每次 OS 调用 drawRect 时,您也会在那里添加另一个子视图。例如,我 运行 你的代码,将颜色从黑色更改为红色、绿色、蓝色,并触发 drawRect 再次调用几次,当我查看视图层次结构时在视图调试器中,您可以看到视图层次结构中的所有视图:

这是一种危险的做法,因为这些子视图会随着时间的推移累加起来,占用内存。

如果您要添加子视图,我建议 (a) drawRect 不是添加子视图的正确位置; (b) 如果您决定采用 addSubview 方法,请决定是否可以在添加新子视图之前删除以前的子视图。

就我个人而言,如果我想 drawRect 画不同颜色的圆圈,我会 stroke UIBezierPath。例如:

class CircleView: UIView {

    var redd1: CGFloat = 0.0 {
        didSet {
            setNeedsDisplay()
        }
    }

    var greenn1 : CGFloat = 0.0 {
        didSet {
            setNeedsDisplay()
        }
    }

    var bluee1: CGFloat = 0.0 {
        didSet {
            setNeedsDisplay()
        }
    }

    override func drawRect(rect: CGRect) {
        let color = UIColor(red: redd1 / 255.0, green: greenn1 / 255.0, blue: bluee1 / 255.0, alpha: 1.0)
        color.setStroke()

        let path = UIBezierPath(arcCenter: CGPoint(x: 75, y: 75), radius: 50, startAngle: 0, endAngle: CGFloat(M_PI * 2.0), clockwise: true)
        path.lineWidth = 2
        path.lineCapStyle = .Round

        path.stroke()
    }

}

顺便说一句,您注意到我们可以完全退休 updateColor。使用上面的代码,如果您设置红色、绿色或蓝色,它将调用 setNeedsDisplay,这将触发视图自动重绘。


您报告上述方法无效。好吧,我用这段代码试过了:

class ViewController: UIViewController {
    @IBOutlet weak var circleView: CircleView!
    @IBOutlet weak var redSlider: UISlider!
    @IBOutlet weak var greenSlider: UISlider!
    @IBOutlet weak var blueSlider: UISlider!

    override func viewDidLoad() {
        super.viewDidLoad()

        redSlider.value = Float(circleView.redd1) / 255.0
        greenSlider.value = Float(circleView.greenn1) / 255.0
        blueSlider.value = Float(circleView.bluee1) / 255.0
    }

    @IBAction func valueChangedForSlider(sender: UISlider) {
        circleView.redd1 = 255.0 * CGFloat(redSlider.value)
        circleView.greenn1 = 255.0 * CGFloat(greenSlider.value)
        circleView.bluee1 = 255.0 * CGFloat(blueSlider.value)
    }
}

而且效果很好: