2012-03-20 16 views
0

私はプロパティcgpathを含むダミーオブジェクトの配列を持っています。これは私のUIViewでdarkPathArrayプロパティと呼ばれます。より高速のデバイスでdrawRectの動作が変わってしまう

私はそれらを次々に描くときに、私は興味深いことが起こることを発見しました。 iOS 5 sim/deviceで実行している場合、EXC_BAD_ACCESSはCGContextAddPath(context,ppath.path);ppath.path)です。しかしNSLogコールをCGContextAddPathの前に置くと正しく動作します。そして、これはかなり遅くなっているからです。

したがって、この問題は、-drawRectの呼び出しの頻度にあります。それは大丈夫です、私はそれを作るまでそれを偽造することができましたが、それはプロの仕方ではありません。

私はなぜこれが起こっているのか尋ねていますか?

-(void)drawRect:(CGRect)r 
{ 
    // Get the graphics context and clear it 
    CGContextRef context = UIGraphicsGetCurrentContext(); 
    CGContextClearRect(context, self.bounds); 

    [[UIColor whiteColor] set]; 
    UIRectFill ([self bounds]); 

    // Draw every single section as a path 
    for (ShopSection *section in self.shopSectionsArray) { 
     // Draw the walls 
     [section.darkColor setFill]; 

     for (MMPath *ppath in section.darkPathArray) { 
      CGContextAddPath(context,ppath.path); 
      CGContextDrawPath(context, kCGPathFill); 
     } 
    } 
} 

編集: ARCは

MMPathsはなぜ(これらは配列に安全に保存されている)

スーパー

EXC_BAD_ACCESSが悪いセクションオブジェクトに応答している/知らない変更されていない使用可能にUIScrollView レイヤー:CATiledLayer

不正アクセスの問題は、c速いデバイス/シミュレーター上で、または激しくスクロールしたりズームしたりすると、迅速に再描画されます。

編集2: 私はそれを得たと思う!問題は、CATiledLayerがバックラウンドスレッドを描画するため、何とかそれが尾を引っ掛けてしまうことです。どのように修正するか考えてみましょうか?そのための最善のアプローチは何ですか?私は間違って何をしていますか?

+1

は、ARCが有効かいませんか? –

+0

このコード中にself.shopSectionsArrayまたはsection.darkPathArrayまたは 'MMPaths'のいずれかが変更されていますか?多分別のスレッドで? –

+0

はい、ARCが有効です。いいえ、MMPathsは他のコードでは変更されません。 – KutakMir

答えて

0

は、私は最終的に私の心を変更し、代わりに私のMMPath(CGPathにプロパティでNSObjectの)のCAShapeLayerを使用しました。その後、CGRectIntersectsRectを使用して、私はそのマルチスレッドバグを取り除くことができました。 これはまた、適切な形状だけが各矩形に描かれるので、最適化を意味する。

だからCATiledLayerで複数の図形を作成しなければならない方法は次のとおりです。

-(void)drawRect:(CGRect)rect 
{ 
// Get the graphics context and clear it 
CGContextRef context = UIGraphicsGetCurrentContext(); 
CGContextClearRect(context, self.bounds); 

[[UIColor whiteColor] set]; 
UIRectFill ([self bounds]); 

// Draw every single section as a path 
for (ShopSection *section in self.shopSectionsArray) { 

    CAShapeLayer *s = section.wallsShapeLayer; 
    // Draw the walls 
    if (CGRectIntersectsRect(rect, s.frame)) 
    { 
     // Rasterising before rendering enhances the performance a bit 
     s.shouldRasterize = YES; 
     [s renderInContext:context]; 
    } 
} 
} 
+0

私もこのことを読むことをお勧めします [記事](http://red-glasses.com/index.php/tutorials/catiledlayer-how-to-use-it-how-it-works-what-it-does/) – KutakMir

1

このループは正しくありません。

for (MMPath *ppath in section.darkPathArray) { 
    CGContextAddPath(context,ppath.path); 
    CGContextDrawPath(context, kCGPathFill); 
} 

CGContextAddPath()はに追加されます "現在のパス。" CGContextDrawPathは「現在のパス」を描画します。だから、パスを延長してから、すべてを再描画します。あなたはこのことを意味:

for (ShopSection *section in self.shopSectionsArray) { 

    // Draw the walls 
    [section.darkColor setFill]; 

    for (MMPath *ppath in section.darkPathArray) { 
     CGContextAddPath(context,ppath.path); 
    } 
} 
CGContextDrawPath(context, kCGPathFill); 
+0

正しくはありません。私はあなたが最も外側のブロックの終わりにCGContextDrawPathを置くことを意味していると思うので、各セクションに適用されます(そしてその色で塗りつぶします)。 –

+0

また、現在のパスに連結していますか?現在のパスをクリアするには、各セクションの先頭に 'CGContextBeginPath()'が必要です。 –

+0

上記のコードはfor()ブロックの外に置いています。 CGContextBeginPathを呼び出す必要はありません(CGContextDrawPathを呼び出す前に)。 CGContextBeginPathを使用する主な理由は、さまざまなスタイルで異なるパスを描画する場合です。 –

関連する問題