5

ARC の下で使用[UIBezierPath CGPath]すると、BAD ACCESS エラーが発生します。CAShapeLayerさまざまな方法でブリッジングを試みましたが、それが問題かどうかはわかりません。makeToPathメソッドの結果を使用してクラッシュを分離しました。

 maskLayer = [CAShapeLayer layer];
 maskLayer.path = [self makeToPath];

しかし、これはクラッシュしません:

 maskLayer = [CAShapeLayer layer];
 maskLayer.path = [self makeFromPath];

によって作成されたパスに何か問題がありますmakeToPathか? このクラッシュを整理したら、 fromパスとtoパスを使用する予定です。から へのCABasicAnimation正しい ARC ブリッジングは?CGPathRefUIBezierPath

-(CGPathRef)makeToPath
{
    UIBezierPath* triangle = [UIBezierPath bezierPath];
    [triangle moveToPoint:CGPointZero];
    [triangle addLineToPoint:CGPointMake(self.view.frame.size.width,0)];
    [triangle addLineToPoint:CGPointMake(0, self.view.frame.size.height)];
    [triangle closePath];
    return [triangle CGPath];
}

-(CGPathRef)makeFromPath
{
    UIBezierPath*rect = [UIBezierPath bezierPathWithRect:self.view.frame];
    return [rect CGPath];
}

更新したがって、以下の回答に従って.hファイルを変更しましたが、まだクラッシュが発生しています

-(CGPathRef)makeToPath CF_RETURNS_RETAINED;
-(CGPathRef)makeFromPath CF_RETURNS_RETAINED;

また、ここでUIBezierPathの回答に従ってメソッドがインスタンスを返すようにしてみました(以下を参照)。まだ成功していません。これを修正する方法について、長い形式で説明したい人はいますか?

maskLayer.path = [[self makeToPath] CGPath];// CRASHES
morph.toValue =  CFBridgingRelease([[self makeToPath] CGPath]);// CRASHES

-(UIBezierPath*)makeToPath
{
    UIBezierPath* triangle = [UIBezierPath bezierPath];
    [triangle moveToPoint:CGPointZero];
    [triangle addLineToPoint:CGPointMake(self.view.frame.size.width,0)];
    [triangle addLineToPoint:CGPointMake(0, self.view.frame.size.height)];
    [triangle closePath];
    return triangle;
}
4

2 に答える 2

8

問題は CGPath を返すことです。返される値は、ARC でカバ​​ーされていない CGPathRef です。作成したUIBezierPathは、メソッドの終了後に解放されます。したがって、CGPathRef も解放します。ソース アノテーションを指定して、ARC に意図を知らせることができます。

.h ファイル内:

-(CGPathRef)makeToPath CF_RETURNS_RETAINED;
-(CGPathRef)makeFromPath CF_RETURNS_RETAINED;
于 2013-01-22T19:35:24.497 に答える
3

他のポスターが指摘したように、メソッドの最後で範囲外になる UIBezierPath オブジェクトから取得した CGPath 参照を返しています。UIBezierPath CGPath プロパティのドキュメントにあるように:

パス オブジェクト自体は UIBezierPath オブジェクトによって所有され、パスにさらに変更を加えるまでのみ有効です。

CGPath のコピーを作成し、それを返す必要があります。

-(CGPathRef)makeToPath
{
    UIBezierPath* triangle = [UIBezierPath bezierPath];
    [triangle moveToPoint:CGPointZero];
    [triangle addLineToPoint:CGPointMake(self.view.frame.size.width,0)];
    [triangle addLineToPoint:CGPointMake(0, self.view.frame.size.height)];
    [triangle closePath];
    CGPathRef theCGPath = [triangle CGPath];
    return CGPathCreateCopy(theCGPath);
}

llvm プロジェクトへのリンクを読んだ方法では、cf_returns_retained 修飾子は、保持を行うのではなく、戻り値のメモリ管理ポリシーを呼び出し元に伝えることを目的としていると思います。

したがって、パスのコピーを作成し、cf_returns_retained 修飾子を追加する必要があると思います。ただし、その修飾子の構文については明確ではありません。(以前は使用していませんでした。)

他の投稿者の構文が正しいと仮定すると、次のようになります。

-(CGPathRef)makeToPath CF_RETURNS_RETAINED;
{
    UIBezierPath* triangle = [UIBezierPath bezierPath];
    [triangle moveToPoint:CGPointZero];
    [triangle addLineToPoint:CGPointMake(self.view.frame.size.width,0)];
    [triangle addLineToPoint:CGPointMake(0, self.view.frame.size.height)];
    [triangle closePath];
    CGPathRef theCGPath = [triangle CGPath];
    return CGPathCreateCopy(theCGPath);
}
于 2013-01-25T21:17:09.680 に答える