Мой взгляд имеет CATiledLayer
. Контроллер представления имеет настраиваемое масштабирование, поэтому -scrollViewDidEndZooming
необходимо перерисовать каждую плитку. Но, несмотря на то, что -setNeedsDisplay
вызывается на слое после каждого увеличения, не все плитки перерисовываются. Это приводит к тому, что вид иногда выглядит неправильно после увеличения. (Вещи, которые должны появиться только в 1 плитке, появляются в нескольких местах). Это часто исправляет себя после другого увеличения.
Вот соответствующий код. updatedRects
предназначен для тестирования - в нем хранятся уникальные прямоугольники, запрошенные для рисования -drawLayer
.
CanvasView.h:
@interface CanvasView : UIView
@property (nonatomic, retain) NSMutableSet *updatedRects;
@end
CanvasView.m:
@implementation CanvasView
@synthesize updatedRects;
+ (Class)layerClass
{
return [CATiledLayer class];
}
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context
{
CGRect rect = CGContextGetClipBoundingBox(context);
[updatedRects addObject:[NSValue valueWithCGRect:rect]];
CGContextSaveGState(context);
CGContextTranslateCTM(context, rect.origin.x, rect.origin.y);
// ...draw into context...
CGContextRestoreGState(context);
}
@end
MyViewController.m:
@implementation MyViewController
- (void)viewDidLoad
{
[super viewDidLoad];
canvasView.updatedRects = [NSMutableSet set];
}
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale
{
canvasView.transform = CGAffineTransformIdentity;
canvasView.frame = CGRectMake(0, 0, canvasView.frame.size.width * scale, canvasView.frame.size.height);
[self updateCanvas];
}
- (void)updateCanvas
{
NSLog(@"# rects updated: %d", [canvasView.updatedRects count]);
[canvasView.updatedRects removeAllObjects];
canvasView.frame = CGRectMake(canvasView.frame.origin.x, canvasView.frame.origin.y, canvasView.frame.size.width, myHeight);
CGFloat tileSize = 256;
NSLog(@"next # rects updated will be: %f", [canvasView.layer bounds].size.width / tileSize);
[canvasView.layer setNeedsDisplay];
}
@end
При тестировании этого я всегда прокручивал весь вид после масштабирования, чтобы убедиться, что каждая плитка была видна. Всякий раз, когда представление выглядело неверно, прогнозируемое «следующее количество обновленных ректов» было больше, чем фактическое «количество обновленных ректов» при следующем вызове -updateCanvas
. Что вызвало бы это?
Редактировать:
Вот лучший способ визуализировать проблему. Каждый раз, когда вызывается updateCanvas
, я заставляю его менять цвет фона для рисования плиток и записывать время, когда он вызывался - цвет и время сохраняются в canvasView
. На каждой плитке нарисован прямоугольник плитки, индекс плитки по оси x, время (в секундах), когда был задан цвет фона, и время (секунды), когда эта плитка была нарисована. Если все работает правильно, все плитки должны быть одного цвета. Вместо этого вот что я иногда вижу:
Кажется, я вижу неправильные результаты только после уменьшения масштаба. Проблема может быть связана с тем фактом, что scrollViewDidEndZooming
, и, следовательно, updateCanvas
, могут вызываться несколько раз за уменьшение. ( Edit : Нет - не вызывается несколько раз.)