Funkcja secItemCopyMatching zwraca dane zerowe

Po pierwsze, oglądałem sesję WWDC 2013 na temat ochrony tajemnic za pomocą pęku kluczy. Chcę zrobić podstawowy sklep z hasłami. Obejrzałem cały film, ale znalazłem to, czego potrzebowałem w pierwszych 10 minutach filmu. Wydaje się to proste, ale nie do końca rozumiem, jak działa kodowanie i pobieranie danych.

PROBLEM: po dopasowaniu secItemCopy sprawdzam mój obiekt NSData, aby upewnić się, że nie jest zerowy przed konwersją do NSString. Problem polega na tym, że zawsze jest zero. Poniżej przedstawiam sposób zapisywania wpisu lub aktualizacji pęku kluczy, a następnie sposób pobierania. Każda pomoc i wyjaśnienie byłyby bardzo mile widziane.

UPDATE (EDITED): Fruity Geek, dzięki za odpowiedź. Zaktualizowałem mój kod poniżej, używając __bridge. Mój problem sprowadza się teraz do tego, czy prawidłowo przechowuję i odzyskuję hasło? Czy mam zarówno złe, jak i jedno lub drugie? Moja instancja NSData jest zawsze zerowa. Sprawdzam kody powrotne, a moje SecItemAdd i SecItemUpdate (gdy istnieje wpis keychaing) działają poprawnie. Nie mogę pobrać wartości ciągu zapisanych danych (hasła), aby porównać je z hasłem wprowadzonym przez użytkownika. Doceń facetów i dziewczęta z pomocy. Oto co robię teraz:

UPDATE # 2: (Edytowane za pomocą odpowiedzi Fruity Geek i ostatecznej wersji roboczej. Moje edycje obejmują tylko zmiany w poniższym kodzie).

Ustaw wpis pęku kluczy:

NSData *secret = [_backupPassword dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *query = @{
    (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
    (__bridge id)kSecAttrService: twServiceName,
    (__bridge id)kSecAttrAccount: twAccountName,
    (__bridge id)kSecValueData: secret,
};
OSStatus status =
    SecItemAdd((__bridge CFDictionaryRef)query, NULL);

if (status == errSecDuplicateItem) {
    // this item exists in the keychain already, update it
    query = @{
        (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
        (__bridge id)kSecAttrService: twServiceName,
        (__bridge id)kSecAttrAccount: twAccountName,
    };
    NSDictionary *changes = @{
        (__bridge id)kSecValueData: secret,
    };
    status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)changes);
}

Pobierz hasło z pęku kluczy:

NSDictionary *query = @{
    (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
    (__bridge id)kSecAttrService: twServiceName,
    (__bridge id)kSecAttrAccount: twAccountName,
    (__bridge id)kSecReturnData: @YES,
};
NSData *data = NULL;
CFTypeRef dataTypeRef = (__bridge CFTypeRef)data;
OSStatus status =
    SecItemCopyMatching((__bridge CFDictionaryRef)query, &dataTypeRef);

NSData *data = (__bridge NSData *)dataTypeRef;

NSString *passcode = @"none";
if (status == errSecSuccess) {
    // we found a keychain entry, set the passcode
    if (data)
        passcode = [NSString stringWithUTF8String:[data bytes]];
}

twServiceName i twAccountName to statyczne NSStrings.

Jak już powiedziałem, nie do końca robię to z __bridge lub CFTypeRef. Przeglądałem dokumenty jabłek, liczne posty tutaj i inne witryny, ale breloczek do kluczy i te terminy są dla mnie zupełnie nowe i nadal próbuję to rozgryźć. Mam nadzieję, że ktoś tutaj może wskazać mój błąd i pomóc mi zrozumieć. Z góry dziękuję za pomoc.

iOS 7 / Xcode 5

questionAnswers(1)

yourAnswerToTheQuestion