2011-03-04 5 views
3

내보기에 CATiledLayer이 있습니다. 뷰 컨트롤러에는 사용자 정의 확대/축소 동작이 있으므로 -scrollViewDidEndZooming에 모든 타일을 다시 그려야합니다. 그러나 모든 줌 후에 레이어에서 -setNeedsDisplay이 호출 되더라도 모든 타일이 다시 그려지지는 않습니다. 이로 인해 확대/축소 이후보기가 때때로 잘못된 것처럼 보입니다. (단 하나의 타일에 나타나는 것이 여러 장소에 나타납니다). 종종 다른 확대/축소 후 자체를 수정합니다.CATiledLayer 이후에 모든 타일을 다시 그려지는 않습니다. -setNeedsDisplay

다음은 관련 코드입니다. 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 축의 타일 인덱스, 배경색이 설정된 시간 (초) 및 타일을 그릴 때의 시간 (초)이 그려집니다. 모든 것이 올바르게 작동하면 모든 타일이 같은 색상이어야합니다. 대신, 여기에 내가 가끔보고 있어요 무엇 : 만 축소 한 후 잘못된 결과를 볼 것

Screenshot of tiles with mismatched colors Screenshot of tiles with mismatched colors

. 문제는 scrollViewDidEndZooming, 따라서 updateCanvas이 축소 당 여러 번 호출 될 수 있다는 사실과 관련이 있습니다. (편집이 : 여러 번 호출하지 말아요 -.)

+1

이것은 CATiledLayer의 버그와 관련이있을 수 있습니다. 타일을 그리는 과정에서 "setNeedsDisplay"를 호출하면 타일이 다시 그려지지 않습니다. – fishinear

답변

10

당신을 위해 작동 할 수 다소 비싼 해킹 있습니다 :

tiledLayer.contents = nil; 
[tiledLayer setNeedsDisplayInRect:tiledLayer.bounds]; 

을 내가 올바르게 기억, 첫 번째 줄은 실제로 타일을 회전 레이어를 일반 레이어로 바꾸지 만 두 번째 줄은 다시 레이어를 바꿉니다. 그러나, 그것은 바둑판 식으로 배열 된 레이어의 모든 것을 던져 버릴 것입니다.

+0

감사합니다. 그러나이 코드를 어디에 두어야하는지 이해할 수 없습니다. 바둑판 식 레이어 인스턴스에 대한 액세스 권한이 drawLayer에있는 곳만 볼 수 있습니다. 거기에 코드를 삽입하면 레이어가 전혀 그려지지 않습니다. 도움 주셔서 감사합니다. –

+0

이제 setNeedsDisplay를 어디에 두어야할까요? 바둑판 식으로 배열 한 레이어는 뷰의 루트 레이어 인 canvasView.layer입니다. – fishinear

관련 문제