调用一个计时器来更新swift的path

我有这个代码,它工作很好

class CircleView: UIView { required init(coder aDecoder: NSCoder) { super.init(coder: aDecoder)! } override init(frame: CGRect) { super.init(frame: frame) } func degreesToRadians (number: Int) -> CGFloat { return CGFloat(number) * CGFloat(M_PI) / 180.0 } override func drawRect(rect: CGRect) { let startAngle: CGFloat = degreesToRadians(0) let endAngle: CGFloat = degreesToRadians(270) let radius: CGFloat = 40.0 let path = UIBezierPath(arcCenter: center, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: true) UIColor.greenColor().setFill() path.addLineToPoint(center) path.fill() } } 

但正如你看到的值是dynamic的(硬编码),我想改变取决于定时器的值,所以我添加了一个计时器和一个函数来更新值。 我的代码变成这样:

 class CircleView: UIView { required init(coder aDecoder: NSCoder) { super.init(coder: aDecoder)! } let startAngle: Double = 0 var counter = 0 let numberOfMinutes = 60 var path: UIBezierPath? var endAngle : Double { get { counter++ return 360 - Double(360/60 * (counter)) } } override init(frame: CGRect) { super.init(frame: frame) } func degreesToRadians (number: Double) -> CGFloat { return CGFloat(number) * CGFloat(M_PI) / 180.0 } override func drawRect(rect: CGRect) { let startAngleRadiant: CGFloat = degreesToRadians(startAngle) let endAngleRadiant: CGFloat = degreesToRadians(endAngle) let radius: CGFloat = 40.0 path = UIBezierPath(arcCenter: center, radius: radius, startAngle: startAngleRadiant, endAngle: endAngleRadiant, clockwise: true) UIColor.greenColor().setFill() path!.addLineToPoint(center) path!.fill() let timer = NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: "update", userInfo: nil, repeats: true) timer.fire() } func update() { print("counter = \(counter)") let startAngleRadiant: CGFloat = degreesToRadians(startAngle) let endAngleRadiant: CGFloat = degreesToRadians(endAngle) let radius: CGFloat = 40.0 path = UIBezierPath(arcCenter: center, radius: radius, startAngle: startAngleRadiant, endAngle: endAngleRadiant, clockwise: true) UIColor.greenColor().setFill() path!.addLineToPoint(center) path!.fill() } } 

我的问题是: 首先屏幕上的圆圈没有改变,它是从第一次调用中画出来的,然后是没有改变的,

其次,我在日志上有这个:

 counter = 1 counter = 2 Nov 17 00:51:51 grab a table[5132] <Error>: CGContextSetFillColorWithColor: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable. Nov 17 00:51:51 grab a table[5132] <Error>: CGContextSaveGState: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable. Nov 17 00:51:51 grab a table[5132] <Error>: CGContextSetFlatness: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable. Nov 17 00:51:51 grab a table[5132] <Error>: CGContextAddPath: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable. Nov 17 00:51:51 grab a table[5132] <Error>: CGContextDrawPath: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable. Nov 17 00:51:51 grab a table[5132] <Error>: CGContextRestoreGState: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable. counter = 3 

我不知道为什么在第三次迭代之后抛出这些错误。

我在做什么错在计时器? 每次函数更新被调用时,我应该构buildpath吗?

你需要在drawRect中完成你所有的绘图。 drawRect是将像素推到屏幕上的函数。 如果你想dynamic改变你的视图的绘制方式,你应该创build你可以设置的属性(很可能是通过视图控制器),然后实现它们的didSet函数并调用setNeedsDisplay,这样你的视图就会被新的参数重绘。 例如:

 var lineWidth: CGFloat { didSet { self.setNeedsDisplay() } } 

要么

 var circlePath: UIBezierPath { didSet { self.setNeedsDisplay() } } 

将circlePath保留为一个variables,然后将drawRect更改为

 override func drawRect(rect: CGRect) { UIColor.greenColor().setFill() if self.circlePath !=nil{ self.circlePath.addLineToPoint(center) self.circlePath.fill() } } 

然后移动

 func degreesToRadians (number: Int) -> CGFloat { return CGFloat(number) * CGFloat(M_PI) / 180.0 } let startAngle: Double = 0 var counter = 0 let numberOfMinutes = 60 var endAngle : Double { get { counter++ return 360 - Double(360/60 * (counter)) } } func update() { print("counter = \(counter)") let startAngleRadiant: CGFloat = degreesToRadians(startAngle) let endAngleRadiant: CGFloat = degreesToRadians(endAngle) let radius: CGFloat = 40.0 path = UIBezierPath(arcCenter: center, radius: radius, startAngle: startAngleRadiant, endAngle: endAngleRadiant, clockwise: true) self.circleView.circlePath = path } 

到你的视图出现在视图控制器中。获取对它的引用并将其称为circleView。 然后在viewDidLoad的地方:

 let timer = NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: "update", userInfo: nil, repeats: true) timer.fire()