4

私の見解には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

これをテストするとき、ズームした後は常にビュー全体をスクロールして、すべてのタイルが表示されていることを確認しました。ビューが間違っているように見えるときはいつでも、予測された「更新されたrectの次の数」は、への次の呼び出しでの実際の「更新されたrectの数」よりも大きかった-updateCanvas。これは何が原因でしょうか?

編集:

問題を視覚化するためのより良い方法は次のとおりです。が呼び出されるたびupdateCanvasに、タイルを描画するための背景色を変更し、呼び出された時刻を記録するようにしました。色と時刻はに保存されcanvasViewます。各タイルには、タイルの長方形、x軸に沿ったタイルのインデックス、背景色が設定された時間(秒)、およびタイルが描画された時間(秒)が描画されます。すべてが正しく機能している場合は、すべてのタイルが同じ色である必要があります。代わりに、これが私が時々見ているものです:

色が一致しないタイルのスクリーンショット 色が一致しないタイルのスクリーンショット

ズームアウトした後、間違った結果が表示されるだけのようです。この問題は、がズームアウトごとに複数回呼び出される可能性があるという事実に関連している可能性がありますscrollViewDidEndZoomingupdateCanvas編集:いいえ-複数回呼び出されません。)

4

1 に答える 1

10

あなたのために働くかもしれないかなり高価なハックがあります:

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

正しく思い出せば、最初の行は実際にはタイルレイヤーを通常のレイヤーに変えますが、2番目の行はそれを元に戻します。ただし、タイルレイヤー内のすべてのものが破棄されます。

于 2011-03-11T10:19:30.637 に答える