[iOS] CFTypeRefをARC下でAutoreleaseしつつReturnする

2013/03/31

こんにちは。きんくまです。

この方法であっているかわからないのですが、一応メモ。

やりたいこと

CoreFoundationのObjectをAutoreleaseしつつReturnしたいことがあります。

私の場合、CGImageRefとかCGContextRefとかがそうでした。

非ARCの場合はこんな感じにやればOKでした。
>> Returning an autorelease’d CFTypeRef with ARC

- (CGImageRef)image {
    CGImageRef myImage;
    id myImageID = (id)myImage;
    [myImageID autorelease];
    return myImage;
}

でこれをどうやってARC下でやればよいのかなーと思いまして。
上のURL先ではns_returns_autoreleasedというのでやっているみたいなのですが、あんまり聞いたことないので、わりと普通っぽいやり方でできないのかなと。

解決方法?

この本とにらめっこすると、以下の3つのキーワードがよさそうな感じでした。

__autoreleasing これつけたものに代入するとautoreleaseしてくれる
__bridge_transfer これやると代入元がreleaseされる
__bridge オーナーシップは変更しないでCoreFoundationとObjective-Cのオブジェクトを変換できる

なんで、これらを利用してARCなしでうまくいっていたのを書き換えてやるとこんな感じになりました。

- (CGImageRef)image {
    CGImageRef myImage;

     //右辺でmyImageをreleaseしつつ左辺に代入。
     //左辺では__autoreleasingがついているのであとでautoreleaseされる
     id __autoreleasing myImageObj = (__bridge_transfer id)myImage;

     //このままだとObjective-Cのオブジェクトなので、CoreFoundationに戻してあげる。
     //その際オーナーシップは変更しないので、__bridgeでキャストする
    return (__bridge CGImageRef)myImageObj;
}

上のコードは本当に宣言して代入しているだけなんで意味はないのですが、実際にはこんな感じに使われるかと

- (CGImageRef)sampleReturnAutoreleasingImageInContext:(CGContextRef)ctx
{
    CGImageRef myImage = CGBitmapContextCreateImage(ctx);
    
    id __autoreleasing myImageObj = (__bridge_transfer id)myImage;
    return (__bridge CGImageRef)myImageObj;
}

これで、Analyzeしてもエラーがでなくなって、Profileでリーク漏れチェックしても出てないので大丈夫かと思いますが、自信がないので使う人がいたら自己責任でお願いしますです。


自作iPhoneアプリ 好評発売中!
フォルメモ - シンプルなフォルダつきメモ帳
ジッピー電卓 - 消費税や割引もサクサク計算!

ページトップへ戻る