2011-03-04 32 views
3

之後重新繪製我的視圖有CATiledLayer。視圖控制器具有自定義縮放行爲,因此在-scrollViewDidEndZooming上每個tile都需要重繪。但是,即使在每次縮放後在圖層上調用-setNeedsDisplay,但並非所有圖塊都正在重繪。這導致視圖在縮放後有時看起來不正確。 (應該只出現在1個貼圖中的東西出現在多個位置)。它經常在另一次縮放後自行糾正。並非所有瓷磚在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 

當測試這一點,我一直滾動所有跨視圖方式放大後確保每個瓷磚都被看到。每當視圖看起來不正確時,預計的「更新的下一個rect」大於下次調用-updateCanvas時實際的「rects更新次數」。什麼會造成這種情況?

編輯:

這裏有一個更好的方式來可視化的問題。每次調用updateCanvas時,我都會更改背景顏色以繪製圖塊並記錄調用時間 - 顏色和時間存儲在canvasView中。在每個圖塊上繪製圖塊的矩形,沿x軸的圖塊索引,設置背景顏色的時間(秒),以及繪製圖塊時的時間(秒)。如果一切正常,所有瓷磚應該是相同的顏色。相反,這裏就是我有時看到:

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

我只依稀看到縮小後錯誤的結果。 此問題可能與 scrollViewDidEndZooming,因此 updateCanvas每次縮小可能被調用多次有關。 編輯:No--不是多次調用。)

+1

這可能與CATiledLayer中的一個錯誤有關:如果您在繪製圖塊的過程中調用「setNeedsDisplay」,則該圖塊將不會重繪。 – fishinear 2012-08-02 10:07:20

回答

10

有一個相當昂貴的黑客可能會爲你工作:如果我沒有記錯

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

,第一行實際上變成平鋪圖層轉換爲普通圖層,但第二行將其轉回。但是,它會將所有內容都扔進平鋪層。

+0

謝謝,但我不明白你把這段代碼放在哪裏。我看到你可以訪問平鋪圖層實例的唯一位置在drawLayer中。如果我把代碼放在那裏,我的圖層根本不會繪製。 感謝您的幫助。 – 2011-10-20 07:46:02

+0

你應該把它放在你現在要做setNeedsDisplay的地方。平鋪圖層是視圖的根層:canvasView.layer。 – fishinear 2012-08-02 10:10:03