在手势处理程序中iOS绘制上下文NULL

时间:2014-07-26 22:42:55

标签: ios objective-c gestures

我无法在iOS中绘制以回应手势事件,我确信这是因为我可能错过了一些非显而易见的基本iOS编程概念。

无论如何,似乎当代码执行以响应事件时,UIGraphicsGetCurrentContext()返回NULL。我不明白为什么。在View的drawRect方法中,其他绘图代码也可以正常工作。

我可以看到事件正在被记录,因为我正在记录它。只是UIGraphicsGetCurrentContext在执行内部事件处理代码时返回null(即使该代码是View类中设置事件处理的函数?

此外,还会记录此错误:

<Error>: CGContextSetFillColorWithColor: 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.

这是相关的代码位,我希望有一些显而易见的东西:

@implementation MainView: UIView

- (id)initWithCoder:(NSCoder *)aDecoder;
{
    self = [super initWithCoder:aDecoder];
    if (self) {
        [self setupEvents];
    }
    return self;
}

- (void)setupEvents {
    UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc]
                                             initWithTarget:self
                                             action:@selector(showGestureForTapRecognizer:)];
    tapRecognizer.numberOfTapsRequired = 1;
    [self addGestureRecognizer:tapRecognizer];
}

- (IBAction)showGestureForTapRecognizer:(UITapGestureRecognizer *)recognizer {

    // Get the location of the gesture
    CGPoint location = [recognizer locationInView:self];
    NSLog(@"got a tap at (%f,%f)", location.x, location.y);
    [self drawCircleX:location.x Y:location.y Radius:5 Color:([UIColor blackColor].CGColor)];
}

- (void) drawCircleX:(int)x Y:(int)y Radius:(int)radius Color:(CGColorRef)fillColor
{
    CGContextRef context = UIGraphicsGetCurrentContext();  // null if called from event handler
    NSLog(@"context=0x%08lx", context);
    //    CGContextSaveGState(context);
    CGRect rect = CGRectMake(x-radius,y-radius, radius*2, radius*2);
    CGContextSetFillColorWithColor(context, fillColor);
    CGContextFillEllipseInRect(context, rect);
    //    CGContextRestoreGState(context);
}

我已经烧掉了几天试图解决这个问题,阅读了大量的文档,但无济于事。是什么赋予了? (ios新手)

1 个答案:

答案 0 :(得分:4)

在iOS上绘图并不像您认为的那样有效。你不能随便画画。您必须告诉UIKit需要重新绘制某些内容,然后,在将来的某个时刻,它将开始绘制并且您的绘图代码将被执行。

它以这种方式工作的原因很简单:如果当前其他东西位于您想要绘制的圆圈之上,该怎么办?这意味着你不能只是重绘你的圆圈,另一件事必须同时重绘 - 因为它可能有抗锯齿或需要知道它下面的东西。

所以,在showGestureForTapRecognizer结束时,只需这样做:

[self setNeedsDisplayInRect:...rect that needs display...];

或者(如果你不能弄清楚矩形):

[self setNeedsDisplay];

然后实现drawRect:

- (void)drawRect:(CGRect)rect
{
  // do your drawing here
}

最后......这是实现视图绘制的“旧”方法。它存在严重的性能问题,特别是在ARM处理器上。

你应该做的是创建一系列CALayer对象(例如,CAShapeLayer来创建一个椭圆),它将绘制自己。如果没有内置类,则将CALayer子类化并实现drawInContext:。这是现代的方法,也许比你想要的更复杂。但它是更好的选择,因为它具有更好的性能并且很好地支持动画。

如果您曾经使用过HTML / CSS或使用过SVG,这与CALayer的工作方式大致相同。你有一个嵌套的事物树将被绘制到屏幕上,你修改数据而不是直接绘制到GPU。