Метод 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 для всех путей кода.