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 и добавить его в качестве подпредставления для представления контроллера представления.