【问题标题】:Swift takeRetainedValue() and takeUnretainedValue() both EXC_BAD_ACCESSSwift takeRetainedValue() 和 takeUnretainedValue() 都是 EXC_BAD_ACCESS
【发布时间】:2022-09-23 14:25:21
【问题描述】:

我有 objc 函数返回 SecIdentityRef

+ (SecIdentityRef)getSecIdentity {
NSString *resourcePath = [[NSBundle mainBundle] pathForResource:@\"cert1\" ofType:@\"p12\"];
NSData *p12Data = [NSData dataWithContentsOfFile:resourcePath];
NSMutableDictionary * options = [[NSMutableDictionary alloc] init];

[options setObject:@\"123456\" forKey:(id)kSecImportExportPassphrase];

CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);

OSStatus securityError = SecPKCS12Import((CFDataRef) p12Data,
                                         (CFDictionaryRef)options, &items);

if (securityError == noErr && CFArrayGetCount(items) > 0) {
    CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
    SecIdentityRef identityApp =
    (SecIdentityRef)CFDictionaryGetValue(identityDict,
                                         kSecImportItemIdentity);
    CFRelease(items);
    return identityApp;
}

CFRelease(items);
return NULL;
}

我在桥接头中使用此函数导入类,然后在快速代码中使用它

let test = Certificate.getSecIdentity()
let secIdentity = test.takeUnretainedValue()

Certificate.getSecIdentity() 返回 Unmanaged<SecIdentityRef>,其中包含正确的 (?) SecIdentity。

test.takeUnretainedValue()(和test.takeRetainedValue())我收到 Thread 1: EXC_BAD_ACCESS (code=1, address=0x2d13e474f3e0)

我做错了什么?如何获得 SecIdentity?

  • 你说,有一些不确定性,test 里面有正确的SecIdentity。您是说因为您查看了_value 的内容,还是基于调试器在屏幕截图中显示的地址?
  • 因为地址
  • 在这种情况下,最好在返回它的 Obj-C 行上放置一个断点,然后查看实际值。也许放入 printf 或 NSLog 或其他东西。基本上首先验证 Obj-C 代码实际上正在获得正确的SecIdentity。然后走出去,在takeUnretainedValue 之前的 Swift 端再次查看它。确保它至少是相同的数据。我不知道问题出在哪里,但这就是我要开始的地方。

标签: ios swift objective-c


【解决方案1】:

当您从(我相信)任何核心基础集合中检索元素时,集合函数遵循Get-Rule。这意味着您不拥有该元素,直到您明确保留它。因此,在这部分代码中:

SecIdentityRef identityApp = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity);
CFRelease(items);

您基本上释放了itemsidentityApp 并返回一个悬空指针。只需在发布 items 数组之前保留 SecIdentityRef 的实例,如下所示:

CFRetain(identityApp);
CFRelease(items);
return identityApp;

附言因为你的函数可能返回NULL,你最好把结果设为nullable,尤其是在使用Swift时,所以它知道结果是一个可选值:

+ (nullable SecIdentityRef)getSecIdentity

附言你也可能想直接用 Swift 重写你的代码,因为it supports work with SecCertificate

【讨论】:

    猜你喜欢
    • 2017-11-26
    • 1970-01-01
    • 2015-05-16
    • 2016-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多