[FIXED] Swift takeRetainedValue() und takeUnretainedValue() beide EXC_BAD_ACCESS

Ausgabe

Ich habe eine objc-Funktion, die zurückkehrtSecIdentityRef

+ (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;
}

Ich importiere die Klasse mit dieser Funktion in den Bridging-Header und verwende sie dann in Swift-Code

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

Von Certificate.getSecIdentity()Rückgaben Unmanaged<SecIdentityRef>mit korrekter (?) SecIdentity im Inneren.

Geben Sie hier die Bildbeschreibung ein

Am test.takeUnretainedValue()(und test.takeRetainedValue()) erhalte ich
Thread 1: EXC_BAD_ACCESS (code=1, address=0x2d13e474f3e0)

Was ich falsch mache? Wie erhalte ich SecIdentity?

Lösung

Wenn Sie ein Element aus (glaube ich) einer Kernsammlung abrufen, folgen die Sammlungsfunktionen der Get-Rule . Das bedeutet, dass Sie das Element nicht besitzen, bis Sie es ausdrücklich behalten. Also in diesem Teil Ihres Codes:

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

Sie geben im Wesentlichen sowohl itemsals auch frei identityAppund geben einen baumelnden Zeiger zurück (um genau zu sein, eine baumelnde Kernfundament-Referenz). Behalten Sie einfach die Instanz von SecIdentityRefvor Ihrer Veröffentlichung des itemsArrays wie folgt bei:

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

PS Da Ihre Funktion möglicherweise zurückgibt NULL, sollten Sie besser das Ergebnis erstellen nullable, insbesondere wenn Sie mit Swift arbeiten, damit es weiß, dass das Ergebnis ein optionaler Wert ist:

+ (nullable SecIdentityRef)getSecIdentity

PPS Sie können Ihren Code auch direkt in Swift umschreiben, da es die Arbeit mit unterstütztSecCertificate


Beantwortet von –
The Dreams Wind


Antwort geprüft von –
Mildred Charles (FixError Admin)

0 Shares:
Leave a Reply

Your email address will not be published. Required fields are marked *

You May Also Like