0

最近、巨大なライブラリを ARC に移行しましたが、ツールのないセクションが頭を悩ませています。コードは次のとおりです。

+ (NSString *)getKeychainItem:(NSString *)identifier
{
    NSString *fullIdentifier = [NSString stringWithFormat:@"%@%@", kIdentifierPrefix, identifier];

    NSMutableDictionary *queryKeychain;
    OSStatus status = noErr;

    queryKeychain = [NSMutableDictionary dictionary];

    // Set the public key query dictionary.
    [queryKeychain setObject:(__bridge id)kSecClassGenericPassword
                      forKey:(__bridge id)kSecClass];

    // Get the key.
    CFDataRef data;
    CFDictionaryRef queryKeychainCF = (__bridge CFDictionaryRef)queryKeychain;
    status = SecItemCopyMatching(queryKeychainCF, (CFTypeRef *)&data);

    NSData *passwordData = (__bridge_transfer NSData *)data;

    NSString *password;

    if (status == noErr)
    {
        password = [[NSString alloc] initWithBytes:[passwordData bytes]
                                            length:[passwordData length]
                                          encoding:NSUTF8StringEncoding];

    }
    else if (status != errSecItemNotFound)
    {
        NSLog(@"Error getting keychain item %@ -- OSStatus: %lu", identifier, status);
    }

    return password;
}

これは非常に簡単なはずですが、passwordData オブジェクトがオーバーリリースされており、その理由がわかりません。スタック トレースはthisです。に設定passwordDatanilて実行しないと、__bridge__transferクラッシュしません。理由について何か考えはありますか?

どうもありがとう!

4

3 に答える 3

2

私自身は使用していません__bridge_transferが、「passwordData」を次のように変更すると:

NSData *passwordData = (NSData *)data;

XCode は 2 つの推奨事項を提供します。

所有権を譲渡しないでください (コア財団はそれを解放する必要があります):

NSData *passwordData = (__bridge NSData *)data;

所有権の譲渡 (ARC が引き継ぐ):

NSData *passwordData = (NSData *)CFBridgingRelease(data);

__bridge_transfer同じことかもしれませんが、CFBridgingReleaseXCode が推奨する呼び出しの使用に問題はありませんでした。

ARC がメモリを管理していない限り、何かを nil に設定しても、実際には何も解放されません。Core Foundation で明示的に解放したり、所有権を ARC に譲渡したりしない限り、Core Foundation オブジェクトを nil に設定する必要はありません。

あなたが持っている別のオプションはCFRelease(data)、帰国の直前に行い、通常の__bridge.

SecItemCopyMatchingこれはすべて、データのコピーを提供し、それを解放することを除いて、という前提に基づいています。NewCopyは通常これを示すキーワードです。CFGetRetainCount(data)at 別のポイントを使用してカウントを確認することで、さらにデバッグできます。

fullIdentifier が使用されていないことにも気付きました。これは機能全体ですか?

initWithData:encoding:の代わりに使用することもできますinitWithBytes:length:encoding

于 2013-03-13T16:43:43.167 に答える
0

問題は完全に別のオブジェクトにあり、正しいコードが添付されていることがわかりました。

CFDictionaryRef queryKeychainCF = (__bridge_retained CFDictionaryRef)queryKeychain;
status = SecItemCopyMatching(queryKeychainCF, (CFTypeRef *)&data);   
NSData *passwordData = (__bridge_transfer NSData *)data;

SecItemCopyMatchingすべての解決策を試した後、 ARC でメソッドのエラーを読み始め、この回答にたどり着きました。

于 2013-03-13T18:29:10.397 に答える
0

使用するにはキャストCFDataRef する必要がありますNSData

 NSData *passwordData = (NSData *)data;

または、所有権を譲渡せずにブリッジを使用するだけです

NSData* passwordData = (__bridge NSData*) data;
于 2013-03-13T16:43:50.050 に答える