Ios 是否忽略UIColor.setFill()错误消息?
我有两个并排循环的函数来不断绘制两个UIBezierPath,问题是,它们每个都有不同的颜色,所以我需要不断重复Ios 是否忽略UIColor.setFill()错误消息?,ios,swift,uicolor,Ios,Swift,Uicolor,我有两个并排循环的函数来不断绘制两个UIBezierPath,问题是,它们每个都有不同的颜色,所以我需要不断重复UIColor.blackColor().setFill()和UIColor(patternImage:UIImage(名为:“normalpaper.jpg”).setFill(),缺点是它使控制台无法阅读,因为它不断地向你发送警告信息 <Error>: CGContextRestoreGState: invalid context 0x0. This is a seri
UIColor.blackColor().setFill()
和UIColor(patternImage:UIImage(名为:“normalpaper.jpg”).setFill()
,缺点是它使控制台无法阅读,因为它不断地向你发送警告信息
<Error>: CGContextRestoreGState: invalid context 0x0. This is a serious error.
This application, or a library it uses, is using an invalid context and is thereby
contributing to an overall degradation of system stability and reliability. This
notice is a courtesy: please fix this problem. It will become a fatal error in an
upcoming update.
下面是完整的CircleView类
(我对编程还是很陌生,所以可能效率很低)
苹果公司解释了所有这些,我强烈建议在继续使用自定义绘图代码之前阅读。请至少阅读上的部分。
问题是您正在
CircleView
sdrawRect
函数中创建并启动NSTimer
s。绘图调用只能在正确的上下文中进行(这实际上是您看到的错误试图告诉您的)。通过在从NSTimer
调用的函数中进行绘图,实际上是在drawRect
函数外部进行绘图,在这种情况下没有有效的绘图上下文。而且,按照代码的原样,每次系统需要重新绘制视图时,您都将启动新的计时器;随着计时器开始重叠,这可能会很快失控
然而,只要稍微重新安排一下,我们就能做到这一点
请注意:这不一定是处理圆动画的正确方法,但它将解决您所询问的有关无效上下文错误的特定问题
drawRect
中取出所有内容,并将其替换为调用eraseCircle
和drawCircle
x
和y
,以及eraseX
和eraseY
从drawCircle
和eraseCircle
中取出,并将其放在timerDraw
和timerErase
中timerDraw
和timerErase
中直接调用图形代码,而是通过调用来告诉视图系统需要重新绘制视图。这将标记您的视图需要重新绘制,并且视图系统将尽快自动再次调用您的drawRect
函数didmovetoserview
并在那里启动计时器,使计时器再次工作;如果它们已经在运行,您还应该添加逻辑来停止它们//Creating a view capable of painting the circle
class CircleView: UIView {
// Timers
var drawTimer: NSTimer?
var eraseTimer: NSTimer?
//Starting X Pos
var x: CGFloat = 100
var eraseX: CGFloat = 100
//Starting Y Pos
var y: CGFloat = 100
var eraseY: CGFloat = 100
override func drawRect(rect: CGRect) {
eraseCircle()
drawCircle()
}
override func didMoveToSuperview() {
// If we have active timers, stop them
if var drawTimer = self.drawTimer {
// This stops the timer
drawTimer.invalidate()
self.drawTimer = nil
}
if var eraseTimer = self.eraseTimer {
// This stops the timer
eraseTimer.invalidate()
self.eraseTimer = nil
}
// If we're actually part of the view hierarchy, start the timers
if self.superview != nil {
//Creating the looping draw timer
self.drawTimer = NSTimer.scheduledTimerWithTimeInterval(
0.2,
target: self,
selector: Selector("timerDraw"),
userInfo: nil,
repeats: true)
//Creating the looping erase timer
self.eraseTimer = NSTimer.scheduledTimerWithTimeInterval(
0.3,
target: self,
selector: Selector("timerErase"),
userInfo: nil,
repeats: true)
}
}
func drawCircle() {
//Setting the draw color
UIColor.blackColor().setFill()
// Creating the rectangle's size
var drawRect = roundDrawRect(10.0, angle: 7)
//Drawing the rectangle
drawRect.fill()
}
func eraseCircle() {
//Setting the eraser color
UIColor(patternImage: UIImage(named: "normalpaper.jpg")).setFill()
// Creating the rectangle's size
var eraseRect = roundEraseRect(10.0, angle: 7)
//Drawing the rectangle
eraseRect.fill()
}
func timerDraw(){
//Incrementing the coords
++y
++x
self.setNeedsDisplay()
}
func timerErase(){
//Decrementing the coords
eraseX = x - 2
eraseY = y - 2
self.setNeedsDisplay()
}
//Defining the rounded rect erasing (Circle)
func roundEraseRect(radius: CGFloat, angle: CGFloat) -> UIBezierPath {
//Creating the rounded rect (Circle)
var roundedRect = UIBezierPath()
roundedRect.moveToPoint(CGPointMake(eraseX,eraseY))
println(CGPointMake(eraseX,eraseY))
roundedRect.addArcWithCenter(CGPointZero, radius: radius,
startAngle: 0, endAngle: angle ,
clockwise: true)
return roundedRect
}
//Defining the rounded rect drawing (Circle)
func roundDrawRect(radius: CGFloat, angle: CGFloat) -> UIBezierPath {
//Creating the rounded rect (Circle)
var roundedRect = UIBezierPath()
roundedRect.moveToPoint(CGPointMake(x,y))
roundedRect.addArcWithCenter(CGPointZero, radius: radius,
startAngle: 0, endAngle: angle ,
clockwise: true)
return roundedRect
}
}
至于实现您正在尝试的动画的最佳方法,您可以只绘制一次圆,然后在
UIViewController
中使用计时器移动整个视图。或者,可能更好,使用。或者,如果您的最终产品将是一款游戏(甚至类似于游戏),那么不妨看看。您在哪里调用drawCircle()
和eraseCircle()
?上下文在这里很重要,因为您只能在非常特定的时间和地点调用绘图代码。@MikeS嘿,Mike。我在一个自定义类中调用它们,该类添加在ViewController的正上方(而不是内部),它是一个名为CircleView的自定义类(我将其作为viewDidLoad内部的子视图添加),它的子类是一个UIView,因此它可以正确地绘制图像,问题是控制台被错误消息垃圾邮件。我将添加整个类供您检查,以确定您是否愿意。问题在于drawRect
中的计时器。你能解释一下你想用这些做什么吗?@MikeS我想做的是让屏幕上的圆圈每隔0.2秒不断移动+1x+1y
。计时器每0.2秒调用一次drawCircle()
函数,该函数以稍微不同的位置绘制圆。与eraseCircle()
函数相同,在稍微延迟后,在旧圆圈位置上绘制一个背景色圆圈,使其产生被擦除的错觉。或者至少,这是目标,它还没有在屏幕上画出图像。。仍然在解决问题。至少,您应该使用计时器,然后从drawRect
内部移动所有绘图代码。但是请先阅读文档。你不需要线程。我现在会读到,至于移动整个背景,这是行不通的,因为我试图实现的目标有点像一个益智游戏,圆圈以预定的速度移动,你点击屏幕来改变它的周围环境,我也不知道这会转化成精灵工具包,我想我会看看那里。谢谢
//Creating a view capable of painting the circle
class CircleView: UIView {
//Starting X Pos
var x: CGFloat = 100
var eraseX: CGFloat = 100
//Starting Y Pos
var y: CGFloat = 100
var eraseY: CGFloat = 100
//Starting the loop of functions
override func drawRect(rect: CGRect) {
//Creating the looping draw timer
NSTimer.scheduledTimerWithTimeInterval(
0.2,
target: self,
selector: Selector("timerDraw"),
userInfo: nil,
repeats: true)
//Creating the looping erase timer
NSTimer.scheduledTimerWithTimeInterval(
0.3,
target: self,
selector: Selector("timerErase"),
userInfo: nil,
repeats: true)
}
func drawCircle() {
//Setting the draw color
UIColor.blackColor().setFill()
// Creating the rectangle's size
var drawRect = roundDrawRect(10.0, angle: 7)
//Incrementing the coords
++y
++x
//Drawing the rectangle
drawRect.fill()
}
func eraseCircle() {
//Setting the eraser color
UIColor(patternImage: UIImage(named: "normalpaper.jpg")).setFill()
//Decrementing the coords
eraseX = x - 2
eraseY = y - 2
// Creating the rectangle's size
var eraseRect = roundEraseRect(10.0, angle: 7)
//Drawing the rectangle
eraseRect.fill()
}
func timerDraw(){
//DO DRAW LOOP HERE
drawCircle()
}
func timerErase(){
//DO ERASE LOOP HERE
eraseCircle()
}
//Defining the rounded rect erasing (Circle)
func roundEraseRect(radius: CGFloat, angle: CGFloat) -> UIBezierPath {
//Creating the rounded rect (Circle)
var roundedRect = UIBezierPath()
roundedRect.moveToPoint(CGPointMake(eraseX,eraseY))
println(CGPointMake(eraseX,eraseY))
roundedRect.addArcWithCenter(CGPointZero, radius: radius,
startAngle: 0, endAngle: angle ,
clockwise: true)
return roundedRect
}
//Defining the rounded rect drawing (Circle)
func roundDrawRect(radius: CGFloat, angle: CGFloat) -> UIBezierPath {
//Creating the rounded rect (Circle)
var roundedRect = UIBezierPath()
roundedRect.moveToPoint(CGPointMake(x,y))
roundedRect.addArcWithCenter(CGPointZero, radius: radius,
startAngle: 0, endAngle: angle ,
clockwise: true)
return roundedRect
}
}
class ViewController: UIViewController {
//Creating a view capable of painting the circle
class CircleView: UIView {
// Timers
var drawTimer: NSTimer?
var eraseTimer: NSTimer?
//Starting X Pos
var x: CGFloat = 100
var eraseX: CGFloat = 100
//Starting Y Pos
var y: CGFloat = 100
var eraseY: CGFloat = 100
override func drawRect(rect: CGRect) {
eraseCircle()
drawCircle()
}
override func didMoveToSuperview() {
// If we have active timers, stop them
if var drawTimer = self.drawTimer {
// This stops the timer
drawTimer.invalidate()
self.drawTimer = nil
}
if var eraseTimer = self.eraseTimer {
// This stops the timer
eraseTimer.invalidate()
self.eraseTimer = nil
}
// If we're actually part of the view hierarchy, start the timers
if self.superview != nil {
//Creating the looping draw timer
self.drawTimer = NSTimer.scheduledTimerWithTimeInterval(
0.2,
target: self,
selector: Selector("timerDraw"),
userInfo: nil,
repeats: true)
//Creating the looping erase timer
self.eraseTimer = NSTimer.scheduledTimerWithTimeInterval(
0.3,
target: self,
selector: Selector("timerErase"),
userInfo: nil,
repeats: true)
}
}
func drawCircle() {
//Setting the draw color
UIColor.blackColor().setFill()
// Creating the rectangle's size
var drawRect = roundDrawRect(10.0, angle: 7)
//Drawing the rectangle
drawRect.fill()
}
func eraseCircle() {
//Setting the eraser color
UIColor(patternImage: UIImage(named: "normalpaper.jpg")).setFill()
// Creating the rectangle's size
var eraseRect = roundEraseRect(10.0, angle: 7)
//Drawing the rectangle
eraseRect.fill()
}
func timerDraw(){
//Incrementing the coords
++y
++x
self.setNeedsDisplay()
}
func timerErase(){
//Decrementing the coords
eraseX = x - 2
eraseY = y - 2
self.setNeedsDisplay()
}
//Defining the rounded rect erasing (Circle)
func roundEraseRect(radius: CGFloat, angle: CGFloat) -> UIBezierPath {
//Creating the rounded rect (Circle)
var roundedRect = UIBezierPath()
roundedRect.moveToPoint(CGPointMake(eraseX,eraseY))
println(CGPointMake(eraseX,eraseY))
roundedRect.addArcWithCenter(CGPointZero, radius: radius,
startAngle: 0, endAngle: angle ,
clockwise: true)
return roundedRect
}
//Defining the rounded rect drawing (Circle)
func roundDrawRect(radius: CGFloat, angle: CGFloat) -> UIBezierPath {
//Creating the rounded rect (Circle)
var roundedRect = UIBezierPath()
roundedRect.moveToPoint(CGPointMake(x,y))
roundedRect.addArcWithCenter(CGPointZero, radius: radius,
startAngle: 0, endAngle: angle ,
clockwise: true)
return roundedRect
}
}