iOS: CGContextRef drawRect не согласен с вводом

Справочная информация: я хотел бы рисовать блоки, когда пользователь где-то подправить. Если блок есть, я хочу стереть его. Я управляю блоками с помощью 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 ответа

Решение

Я не вижу нигде, где вы на самом деле очищаете то, что нарисовали ранее. Если вы явно не ясно (например, заполнив UIRectFill() - что, кроме этого, является более удобным способом рисования прямоугольников, чем заполнение явного пути), Quartz собирается просто рисовать поверх старого содержимого, что приведет к неожиданному поведению при попытках удаления.

Итак... что произойдет, если вы положите в начале -drawRect::

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

(Это, конечно, ужасно неэффективно, но, согласно вашему комментарию, я игнорирую этот факт.)

(Отдельно, вы, вероятно, должны обернуть свой код рисования в CGContextSaveGState()/CGContextRestoreGState() пара, чтобы не испортить графический контекст любого вызывающего кода.)

РЕДАКТИРОВАТЬ: я всегда забываю об этом свойстве, так как я все равно хочу рисовать более сложные фоны, но вы, вероятно, можете достичь аналогичных результатов, установив clearsContextBeforeDrawing:YES на UIView.

Этот подход кажется мне немного странным, потому что каждый раз, когда вызывается метод touchesEnded, вам нужно перерисовать (что является дорогостоящей операцией), а также необходимо отслеживать квадраты. Я предлагаю вам создать подкласс UIView и реализовать метод drawRect: так, чтобы представление знало, как рисовать себя и реализовывать метод touchesEnded в вашем контроллере представления, где вы можете проверить, коснулись ли вы SquareView, а затем удалить его из представления контроллера представления, в противном случае создайте SquareView и добавить его в качестве подпредставления для представления контроллера представления.

Другие вопросы по тегам