アクトインディ開発者ブログ

子供とお出かけ情報「いこーよ」を運営する、アクトインディ株式会社の開発者ブログです

Toll-free bridge

こんにちは。
masudaです。

今日は節分でしたね。
あの豆を食べるのが好きです。

早くもネタが尽きてきました。
自分がObjective-Cのポテンシャルがわかっていないので(別にObjective-Cである必要は全然ないのですが)、続き物を書くことができません。

今回はToll-free bridgeについて書いてみようと思います。
またもやどこにもあるようなネタです。

Toll-free bridgeについてはHMDTさんなどで詳しく紹介がされています。
ダイナミックObjective-C (38) Toll-free bridge(1) – 変換コスト0のブリッジ | エンタープライズ | マイコミジャーナル

CocoaのオブジェクトとCoreFoundationのオブジェクトを相互にキャストするだけで変換することができます。
たとえばCocoaのNSStringというクラスは、CoreFoundationではCFStringというものに対応します。

具体例を示しましょう。
変換の話の前に、CoreFoundationでは初期化はどうするか?

NSStringであれば

NSString *hoge = [[NSString alloc] initWithCString:"piyo"];

のように書くところですが、CoreFoundationでは

CFStringRef hoge = CFStringCreateWithCString(kCFAllocatorDefault, "piyo", kCFStringEncodingUTF8);

となります。

さて、本題のToll-free bridgeによる変換です。
どのようなときに使うのか?
具体例を挙げると、NSStringの遅いメソッドであるcharacterAtIndexを呼び出す代わりに、CoreFoundationにあるCFStringGetCharacterFromInlineBuffer関数を使用して高速に処理するなんて使い方をするとか。
別にすべてCoreFoundationで書いてもかまいませんが、Cocoaを使うよりも幾分面倒なのでこういう適用が多いのではないかと思います。

NSString                *hoge;
CFIndex                 length, current;
CFStringInlineBuffer    buffer;
UniChar                 ch;

*hoge = [[NSString alloc] initWithCString:"piyo"];
length = CFStringGetLength((CFStringRef)hoge);

CFStringInitInlineBuffer((CFStringRef)hoge, &buffer, CFRangeMake(0, length));

current = 0;
while (current < length)
{
    ch = CFStringGetCharacterFromInlineBuffer(&buffer, current);
    NSLog(@"%c", ch);

    ++current;
}

こんな風にキャストするだけで渡すことができます。
昔、NSDictionaryの生成をCFDictionaryの生成に変えたところ劇的に速度が向上したことがあったような気がします。