間が空いてしまいしましたが最終回は、C言語で書かれたCore Foundation に、Objective-Cが混ざっている時のARCの記述についてです。
※過去の回は以下を参照して下さい。
CoreFundationにもCFRetainやCFReleaseと、オブジェクトの所有(retainCount)に関係する関数がありますが、ARCはObjective-Cだけで有効で、C言語では使えないため、retainカウントの取り扱いについて、以下の修飾子を使って指定し、オブジェクトの所有権を正しく管理する必要があります。
・__bridge
・__bridge_retained
・__bridge_transfer
それぞれの修飾子の意味は以下の通りです。
■__bridge
retainカウントについては何もしない単純な代入。
Objective-Cのポインタ型と、Core Foundationのポインタ型で、相互に代入したいケースで使用します。
■__bridge_retained
代入先でretainする。
修飾子だけでなく、Objective-CのポインタからCore Foundationのポインタへ変換する事を想定した以下の関数も用意されています。
CFTypeRef CFBridgingRetain(id X) {
return (__bridge_retained CFTypeRef)X;
}
■__bridge_transfer
代入先に所有権を移す。(代入後に元のポインタはreleaseされる。)
修飾子だけでなく、C言語のポインタからObjective-Cのポインタへ変換する事を想定した以下の関数も用意されています。
id CFBridgingRelease(CFTypeRef CF_CONSUMED X) {
return (__bridge_transfer id)X;
}
Objective-CはTool-free bridgeと呼ばれる仕組みで、C言語と混在できるようになっていて、CFStringとNSStringのポインタも相互に変換できます。
例えば、CFStringのポインタpCFStrとNSStringのポインタpNSStrがあったとすると、ARC以前では以下のように書いてもエラーがでませんでした。
pCFStr = (CFStringRef)pNSStr;
pNSStr = (NSString *)pCFStr;
ARCではこれらはコンパイルエラーになります。
こういったObjective-CとC言語のポインタの変換時に、前述の修飾子を使う必要があります。
以下のように書いた場合は、pCFStrのretainカウントは変わりません。(NSStringのポインタをCore Foundationのポインタに代入する場合も、retainカウントを変更しない場合は__bridgeを使います。)
pNSStr = (__bridge NSString *)pCFStr;
以下のように書いた場合は、NSStringのポインタに代入した後に、[pNSStr retain]を呼び出したような動作になります。
pNSStr = (__bridge_retained NSString *)pCFStr;
CFReleaseでpCFStrのretainカウントを減らさなければ、ポインタが参照しているオブジェクトのretainカウントは増える事になります。
以下のように書いた場合は、NSStringのポインタに代入した後に、pCFStrをリリースする動作になります。
pNSStr = (__bridge_transfer NSString *)pCFStr;
pNSStrが__strongで定義されていた場合、pNSStrに代入された時点でretainされ、pCFStrはreleaseされるので、結果としてオブジェクトの所有権が移った事になります。
なかなか必要な状況はなさそうですが、Objective-Cのポインタをvoid型のポインタに代入したりする時も考え方は同じです。
Cの構造体のメンバにObjective-Cのポインタを使おうとするとややこしい事になるので、構造体ではなくObjective-Cのオジェクトを使った方が楽だと思います。
C言語が混ざってくるとなかなかややこしい感じのARCですが、上記の修飾子の意味を理解していれば、それほど難しくは無いと思います。
既存のC言語のコードが多い場合は、ARCの設定の回で書いたソース単位でのON/OFFを使って、新しくObjective-Cで各部分だけARCをONにするというのもいいと思います。
iOSのメモリ管理の基礎からARCの設定、ソースの記述まで全4回に分けて書きましたが、これでARCの話題は終わりです。
開発環境がどんどんパワーアップしていって、作りやすくなるのはいい事ですが、作り手が新しい機能に対応していくのもなかなか大変ですね。
※iPhoneアプリ開発に関する投稿を今から始めるiPhoneアプリ開発にまとめました。
最近のコメント