iOS:CGContextRef drawRect不同意输入

时间:2012-04-18 21:27:21

标签: iphone ios drawrect setneedsdisplay cgcontextref

背景:我想在用户触摸某处时绘制块。如果块在那里,我想删除它。我使用NSMutableArray来管理块,以跟踪块应该去的点。每次用户触摸时,它将确定触摸位置是否已经包含块并相应地管理阵列。

问题:我收到了一个非常奇怪的反馈。首先,数组中的所有内容都可以按照我的意愿运行。当用户想要擦除块时问题就出现了。在正确维护数组的同时,绘图似乎忽略了数组中的更改。它除了最后一个点之外不会删除任何东西。当用户点击其他地方时,即使闪烁也会打开和关闭。

以下是代码

- (void)drawRect:(CGRect)rect
{
    NSLog(@"drawrect current array %@",pointArray);
    for (NSValue *pointValue in pointArray){
        CGPoint point = [pointValue CGPointValue];
        [self drawSquareAt:point];
    }
} 

- (void) drawSquareAt:(CGPoint) point{
    float x = point.x * scale;
    float y = point.y * scale; 

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextMoveToPoint(context, x, y);
    CGContextAddLineToPoint(context, x+scale, y);
    CGContextAddLineToPoint(context, x+scale, y+scale);
    CGContextAddLineToPoint(context, x, y+scale);
    CGContextAddLineToPoint(context, x, y);

    CGContextSetFillColorWithColor(context, [UIColor darkGrayColor].CGColor);
    CGContextFillPath(context);
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *aTouch = [touches anyObject];
    CGPoint point = [aTouch locationInView:self];
    point = CGPointMake( (int) (point.x/scale), (int) (point.y/scale));
    NSLog(@"Touched at %@", [NSArray arrayWithObject: [NSValue valueWithCGPoint:point]]);

    NSValue *pointValue = [NSValue valueWithCGPoint:point];
    int i = [pointArray indexOfObject:pointValue];
    NSLog(@"Index at %i",i);
    if (i < [pointArray count]){
        [pointArray removeObjectAtIndex:i];
        NSLog(@"remove");
    }else {
        [pointArray addObject:pointValue];
        NSLog(@"add");
    }
    NSLog(@"Current array : %@", pointArray);

    [self setNeedsDisplay];
}

scale定义为16。 pointArray是视图的成员变量。

要测试:您可以将其放入任何UIView并将其添加到viewController以查看效果。

问题:如何让绘图与数组一致?


更新+说明:我知道这种方法的成本,但它只是为我创建一个快速的数字。它不会在实际应用中使用,因此,请不要挂断它有多贵。我只创建了这个功能,以获得我绘制的数字的NSString@"1,3,5,1,2,6,2,5,5,...")中的值。当我实际使用它而没有重绘时,这将变得更有效。请坚持提问。谢谢。

2 个答案:

答案 0 :(得分:1)

我没有在任何地方看到您实际清除之前绘制的内容。除非你明确清楚(例如填充UIRectFill() - 除了填充显式路径之外,它是一种更方便的绘制矩形的方法),Quartz将只是绘制旧内容,这将在尝试擦除时会导致意外行为。

那么......如果你放在-drawRect:的开头会发生什么:

[[UIColor whiteColor] setFill]; // Or whatever your background color is
UIRectFill([self bounds]);

(这当然是极其低效的,但根据你的评论,我无视这一事实。)

(另外,您可能应该将您的绘图代码包装在CGContextSaveGState() / CGContextRestoreGState()对中,以避免污染任何调用代码的图形上下文。)

编辑:我总是忘记这个属性,因为我通常想要绘制更复杂的背景,但是你可以通过在UIView上设置clearsContextBeforeDrawing:YES来获得类似的结果。

答案 1 :(得分:0)

这种方法对我来说似乎有点奇怪,因为每次调用touchesEnded方法时你需要重绘(这是一项昂贵的操作)并且还需要跟踪方块。我建议你继承一个UIView并实现drawRect:方法,这样视图就知道如何绘制自己并在视图控制器中实现touchesEnded方法,在那里你可以检查你是否触摸过squareView然后从视图控制器的视图中删除它,否则创建一个squareView并将其作为子视图添加到视图控制器的视图中。