2011-10-19 5 views
9

古いプロジェクトを自動参照カウントに変換しようとしています。私はxCodeが持っている変換ツールを使用しようとしていますが、変換する前にいくつかの問題を修正すると言います。このエラーを修正する方法はわかりません。これはキーチェーンファイルの実装にあります。このメソッドはエラーを返します。具体的には、SecItemCopyMatchingの行です。 "CFTypeRef * '(別名const void **')へのObjective-Cポインタへの間接的なポインタのキャストは、ARCでは禁止されています。私はgoogle、apple docs、およびその他のがらくたの束とキーチェーン内の既存のデータ・ディクショナリを取得するためのより良い方法を見つけることができません。すべてのヘルプは感謝。感謝!iPhoneでキーチェーンからデータ辞書を取得

-(NSMutableDictionary*)fetchDictionary { 

NSMutableDictionary *genericPasswordQuery = [self buildSearchQuery]; 

NSMutableDictionary *outDictionary = nil; 
OSStatus status = SecItemCopyMatching((__bridge_retained CFDictionaryRef)genericPasswordQuery, (CFTypeRef*)&outDictionary); 

if (DEBUG) printf("FETCH: %s\n", [[self fetchStatus:status] UTF8String]); 

if (status == errSecItemNotFound) return NULL; 
return outDictionary; 

}

答えて

41

あなたはARCを無効にする必要はありませんそのためには、クエリの結果をCFDictionaryRefとして宣言し、呼び出し後にNSDictionaryにキャストしてください。

/*1*/ CFDictionaryRef cfquery = (__bridge_retained CFDictionaryRef)genericPasswordQuery; 
/*2*/ CFDictionaryRef cfresult = NULL; 
/*3*/ OSStatus status = SecItemCopyMatching(cfquery, (CFTypeRef *)&cfresult); 
/*4*/ CFRelease(cfquery); 
/*5*/ NSDictionary *result = (__bridge_transfer NSDictionary *)cfresult; 
発言の

カップル:1行目で

  • 、私たちはココアの土地からのCore Foundationの国にクエリを変換します。 __bridge_retainedを使用して、作業中にARCがオブジェクトを解放したり解放したりしないようにします。この種のブリッジキャストはオブジェクトを保持しているので、漏れを防ぐためには対応するCFReleaseを必ず実行しなければなりません。 SecItemCopyMatchingは私たちのために質問を確実にリリースしないでしょう。したがって、保持されたブリッジを使用する場合は、結果として得られるCore Foundationオブジェクトをリリースする必要があります。 (これは4行目で行っています)
  • 2行目、3行目、4行目はCore Foundationタイプを使用した純粋なCコードなので、ARCは何もしないで文句を言います。
  • 5行目では、SecItemCopyMatchingが保持カウント1の結果を作成したことをARCに伝えます。 (名前に "Copy"が含まれているのでこれを知っています)__bridge_transferはARCにこの責任について知らせるので、自動的に私たちのためにそれを行うことができます。
  • SecItemCopyMatchingから返された不変のCore FoundationディクショナリをNSMutableDictionaryにキャストしないでください。それは間違っている。また、buildSearchQueryNSMutableDictionaryを返すのは、一般的なココアスタイルの規約に反する。両方のケースでうまくいくでしょう。

ここに親指のルールは、「コピー」または「作成」機能からの結果はココア-土地が__bridge_transferを使用してにキャストする必要がありながら__bridge_retainedニーズは、CFRelease続いすべきです。

+0

アドバイス私はここで同じ質問に関する何かをすることができますhttp://stackoverflow.com/questions/16780202/secitemcopymatching-still-leak-on-osx-under-arc – user170317

0

方法2:一度使用する場合、保持または転送する必要があるのはなぜですか?キーが発見されるとき(memleaks)のデバッグの私にとっては一目で下仕事から例、テスト、すべて合格:)一つだけの事は漏れ未発表autoretained変数をしました()

CFDictionaryRef keyAttributes = NULL; /* variable for store attributes */ 

NSMutableDictionary *credQuery = [NSMutableDictionary dictionary]; // credential Query 

/* Here you add some options for search your key */ 

OSStatus errGather = SecItemCopyMatching(
    (__bridge CFDictionaryRef)credQuery, 
    (CFTypeRef *)&keyAttributes 
); 

if (errGather == errSecSuccess) { 
    // Gather stored key 
    NSDictionary *keychainDict = (__bridge NSDictionary *)keyAttributes; 
    NSData *passData = keychainDict[(__bridge id<NSCopying>)kSecValueData]; // password 
    ... 
    /* work with gathered data :) */ 
    ... 
    CFRelease(keyAttributes); // (1) HERE. Release when CFType is retained really :) 
    credQuery = nil; 
    keychainDict = nil; 
    passData = nil; 
} 
2

方法3:ARCは、やってみましょう重い物を持ち上げる(又は方法1と方法2との組合せ):

NSMutableDictionary* query = [NSMutableDictionary dictionaryWithDictionary: 
@{ 
    (__bridge id) kSecClass : (__bridge id) kSecClassGenericPassword, 
    (__bridge id) kSecAttrService : nssService, 
#if ! TARGET_IPHONE_SIMULATOR 
    (__bridge id) kSecAttrAccessGroup : @"PRODUCT.com.COMPANY.GenericKeychainSuite", 
#endif 

    (__bridge id) kSecMatchLimit : (__bridge id) kSecMatchLimitOne, 
    (__bridge id) kSecReturnAttributes : (__bridge id) kCFBooleanTrue, 
}]; 

if ([nssAccount length] != 0) 
    [query setObject:nssAccount forKey:(__bridge id) kSecAttrAccount]; 

CFDictionaryRef cfresult; 
auto err = ::SecItemCopyMatching((__bridge CFDictionaryRef)query, 
            (CFTypeRef*)&cfresult); 
if (err == errSecItemNotFound) 
    return std::wstring(); 
else if (err != noErr) 
    throw std::exception(); 

NSDictionary* result = (__bridge_transfer NSDictionary*) cfresult; 

SecItemCopyMatching着信辞書を所有する必要がないので、__bridgeが適切 し、次いでARCは、クエリの有効期間を管理し続けます。

結果の所有権をarcに移すことによって、結果の寿命 も管理され、すべてのコード のパスにCFReleaseを覚えておく必要はありません。

関連する問題