web-dev-qa-db-ja.com

iOSブリッジとbridge_transfer

bridgeおよびbridge_transferと混同していますが、これは正しいですか?

-(void)getData{
    ABAddressBookRef addressBook = ABAddressBookCreate();
    NSArray *allPeople = (__bridge_transfer NSArray*)ABAddressBookCopyArrayOfAllPeople(addressBook);

    NSString *name;
    for ( int i = 0; i < [allPeople count]; i++ )
    {
        name = (__bridge_transfer NSString *) ABRecordCopyValue((__bridge ABRecordRef)[allPeople objectAtIndex:i], kABPersonFirstNameProperty);
    }
    CFRelease(addressBook);
    allPeople = nil;
}

使い方を説明してくれる人はいますか?

33
Rinat

自動参照カウント(ARC)がオンになっている場合、コードは正しいです。

ステートメントには2つの__bridge_transferがあります。その結果、作成されたCFObjectsの所有権はNSObjectsに転送されます。 ARCをオンにしている場合、それらは自動的に解放されます。これら2つのステートメントの代わりに__bridgeを使用した場合、CFReleaseを明示的に呼び出して、*Copy AP​​Iによって作成されたCFObjectsを解放する必要があります。

__bridgeステートメントも正しいです。 CF APIでNSObjectを参照しているからです。あなたは所有権を譲渡しないので、ARCはそれを解放します。

42
He Shiming

これは非常に単純です。ARC(自動参照カウント)を使用すると、コンパイラーは変数によってポイントされているオブジェクトの数をカウントします。カウントが0になると、オブジェクトは自動的に割り当て解除されます。 SOコアファンデーションのような低レベルの構造に由来するものの場合、コンパイラーは何をすべきかを知りません。そのため、コンパイラーに「これを無視する、i 「必要なときに解放します」または「これをオブジェクトとして扱い、参照が0になったときに解放する」と言いたい場合は、Bridge転送。

これを行うと、通常の状況では「CFRelease」によって解放されるはずのコピーを作成します。

ABAddressBookCopyArrayOfAllPeople(addressBook)

ただし、これを追加すると、transferringがObjective-Cオブジェクトの所有権になります。

NSArray *allPeople = (__bridge_transfer NSArray*)........

したがって、NSArrayはARCによって管理されます。


JRGが言及しているように、これを行うことに注意してください。

CFRelease(addressBook);

とにかく新しく作成されたオブジェクトには影響しませんが、代わりに、手動で解放する必要がある元のオブジェクトに影響します(通常、これらのメソッドにはcreateまたはcopyがあるため、簡単にわかります) =名前に含まれるキーワード)


コードでは発生しませんが、CFReleaseでNULLであるコアFoundationオブジェクトを解放するとエラーが発生するので注意が必要です。パウロがコメントで述べているように。

19
Pochi

Luis Oscar私はまだARCの理解に取り組んでいますが、addressBookにはCFReleaseが必要だと思います。 ARCはaddressBookを管理していません。 NSArray * allPeopleは、__ bridge_transferキャストヒントを介してARCによって管理されており、オリジナルのコピーとして作成されています。 CFReleaseがないと、addressBookがリークします。

1
Tuique

1つの編集:nilオブジェクトでCFReleaseを呼び出すとアプリがクラッシュする

0
moliveira