所以我正在尝试将旧项目转换为自动引用计数。我正在尝试使用 xCode 具有的转换工具,但它说要在转换之前修复一些问题。我不知道如何修复这个错误。它在钥匙串(keychain)文件的实现中。此方法会返回错误,特别是带有 SecItemCopyMatching 的行。我收到的错误是:“ARC 不允许将间接指针转换为 Objective-C 指针到‘CFTypeRef*’(又名‘const void**’)。我一直在查看 google、apple 文档,和一堆其他废话,无法找到更好的方法来获取钥匙串(keychain)中的现有数据字典。感谢任何帮助。谢谢!
-(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;
}
最佳答案
您不需要为此禁用 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 行中,我们将查询从 cocoa 土地转换为核心基金会国家/地区。我们使用 __bridge_retained 来确保 ARC 在我们使用对象时不会释放和取消分配该对象。这种桥接强制转换会保留对象,因此为了防止泄漏,必须在其后的某处添加相应的
CFRelease
。 SecItemCopyMatching 肯定不会为我们释放查询,所以如果我们使用保留桥,那么我们需要自己释放生成的 Core Foundation 对象。 (我们在第 4 行中执行此操作。) - 第 2、3 和 4 行是使用 Core Foundation 类型的纯 C 代码,因此 ARC 不会对它们执行任何操作或提示。
- 在第 5 行中,我们告诉 ARC,
SecItemCopyMatching
已创建保留计数为 1 的结果,我们负责释放该结果。 (我们知道这一点是因为它的名称中包含“Copy”。)__bridge_transfer
让 ARC 了解此职责,因此它将能够自动为我们完成此操作。 - 不要将 SecItemCopyMatching 返回的不可变 Core Foundation 字典转换为
NSMutableDictionary
;那是错误的。此外,buildSearchQuery
返回一个NSMutableDictionary
也违反了一般的 Cocoa 风格约定。简单的 NSDictionary 在这两种情况下都可以正常工作。
这里的经验法则是 __bridge_retained
后面需要跟一个 CFRelease
,而“Copy”或“Create”函数的结果必须转换为Cocoa-land 使用 __bridge_transfer
。
关于iPhone从钥匙串(keychain)中获取数据字典,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7827730/