我有这个代码,它运行得很好
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()
}
}
但正如你所看到的,这些值是动态的(硬编码的),我想根据计时器来更改值,所以我添加了一个计时器和一个更新值的函数。我的代码变成这样:
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
我不知道它为什么在第三次迭代之后抛出这些错误。
我在计时器上做错了什么?我应该在每次调用函数update时构造路径吗?
您需要在drawRect中完成所有绘图。drawRect是将像素推送到屏幕上的函数。如果你想动态更改视图的绘制方式,你应该创建可以设置的属性(很可能是由视图控制器设置的),然后实现它们的didSet函数并调用setNeedsDisplay,这样你的视图就会用新参数重新绘制。例如:
var lineWidth: CGFloat {
didSet {
self.setNeedsDisplay()
}
}
或
var circlePath: UIBezierPath {
didSet {
self.setNeedsDisplay()
}
}
保持circlePath为变量,然后将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。然后在视图DidLoad位置:
let timer = NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: "update", userInfo: nil, repeats: true)
timer.fire()