Vin*_*nzo 6 pointers objective-c ios swift
自从两天将一段代码从Objective-C翻译成Swift以来,我一直陷入困境:
CFArrayRef keyref = NULL;
CFDictionaryRef identityDict = CFArrayGetValueAtIndex(keyref, 0);
SecIdentityRef identityRef = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity);
Run Code Online (Sandbox Code Playgroud)
是的,就是这样!我根本无法用这些指针来满足编译器.请帮忙 :-)
这是要翻译的整个目标c代码:
// Read .p12 file
NSString *path = [[NSBundle mainBundle] pathForResource:@"SSLKeyStoreClient" ofType:@"p12"];
NSData *pkcs12data = [[NSData alloc] initWithContentsOfFile:path];
// Import .p12 data
CFArrayRef keyref = NULL;
OSStatus sanityChesk = SecPKCS12Import((__bridge CFDataRef)pkcs12data,
(__bridge CFDictionaryRef)[NSDictionary
dictionaryWithObject:@"wed-zzz"
forKey:(__bridge id)kSecImportExportPassphrase],
&keyref);
if (sanityChesk != noErr) {
NSLog(@"Error while importing pkcs12 [%d]", (int)sanityChesk);
} else
NSLog(@"Success opening p12 certificate.");
// Identity
CFDictionaryRef identityDict = CFArrayGetValueAtIndex(keyref, 0);
SecIdentityRef identityRef = (SecIdentityRef)CFDictionaryGetValue(identityDict,
kSecImportItemIdentity);
// Cert
SecCertificateRef cert = NULL;
OSStatus status = SecIdentityCopyCertificate(identityRef, &cert);
if (status)
NSLog(@"SecIdentityCopyCertificate failed.");
// the certificates array, containing the identity then the root certificate
NSArray *myCerts = [[NSArray alloc] initWithObjects:(__bridge id)identityRef, (__bridge id)cert, nil];
NSMutableDictionary *SSLOptions;
[SSLOptions setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsExpiredRoots];
NSDictionary *settings = [[NSDictionary alloc] initWithObjectsAndKeys:
[NSNumber numberWithBool:YES], kCFStreamSSLAllowsExpiredCertificates,
[NSNumber numberWithBool:YES], kCFStreamSSLAllowsAnyRoot,
[NSNumber numberWithBool:NO], kCFStreamSSLValidatesCertificateChain,
kCFNull,kCFStreamSSLPeerName,
myCerts,kCFStreamSSLCertificates,
nil];
CFReadStreamSetProperty((CFReadStreamRef)self.inputStream, kCFStreamPropertySSLSettings, (CFTypeRef)settings);
CFWriteStreamSetProperty((CFWriteStreamRef)self.outputStream, kCFStreamPropertySSLSettings, (CFTypeRef)settings);
Run Code Online (Sandbox Code Playgroud)
这就是我到目前为止所得到的:
// Read .p12 file
var path = NSBundle.mainBundle().pathForResource("SSLKeyStoreClient", ofType: "p12")
var pkcs12data: NSData = NSData.dataWithContentsOfFile(path, options: nil, error: nil)
// Import .p12 data
var keyref: Unmanaged<CFArray>?
var optionDict: NSMutableDictionary = NSMutableDictionary()
optionDict.setValue("wed-zzz", forKey: kSecImportExportPassphrase!.takeRetainedValue())
var sanityChesk = SecPKCS12Import(pkcs12data,optionDict,&keyref)
if sanityChesk != 0{ //noErr
println("Error while importing pkcs12 \(sanityChesk)")
} else {
println("Success opening p12 certificate.")
}
// Identity
var key = keyref!
var identityDict: CFDictionary = CFArrayGetValueAtIndex(keyref, 0)
var identityRef:COpaquePointer = CFDictionaryGetValue(identityDict,nil)
// Cert
var cert: Unmanaged<SecCertificate>?
var status: OSStatus = SecIdentityCopyCertificate(identityRef, &cert)
if status == 0{
println("SecIdentityCopyCertificate failed.")
}
// the certificates array, containing the identity then the root certificate
var sslOptions = Dictionary<NSObject, NSObject>()
sslOptions[kCFStreamSSLAllowsExpiredRoots] = NSNumber.numberWithBool(true)
var settings = Dictionary<NSObject, NSObject>()
settings[kCFStreamSSLAllowsExpiredCertificates] = NSNumber.numberWithBool(true)
settings[kCFStreamSSLAllowsAnyRoot] = NSNumber.numberWithBool(true)
settings[kCFStreamSSLValidatesCertificateChain] = NSNumber.numberWithBool(false)
settings[kCFStreamSSLPeerName] = kCFNull
//settings[kCFStreamSSLCertificates] = myCerts
CFReadStreamSetProperty(self.inputStream, kCFStreamPropertySSLSettings, settings)
CFReadStreamSetProperty(self.inputStream, kCFStreamPropertySSLSettings, settings)
Run Code Online (Sandbox Code Playgroud)
问题始于:
var identityDict: CFDictionary = CFArrayGetValueAtIndex(keyref, 0)
Run Code Online (Sandbox Code Playgroud)
错误:"非托管CFArray无法转换为CFArray".
到目前为止,这是我最好的尝试.
大概第一行是实际数组的占位符?如果您实际上正在使用NULL
数组指针,则其余代码不会执行任何操作。
假设您从真实的 开始CFArrayRef
,您可以利用桥接:CoreFoundation 类型会自动被视为 Swift 对象,因此您不需要使用CFArrayRef
和CFDictionaryRef
指针。这同样适用于使用 CF 类型系统的任何其他 C API,因此它也应该适用于SecIdentity
.
自动桥接 CF 集合 \xe2\x80\x94 似乎有些奇怪,您可以隐式将 a 桥接到CFArray
an NSArray
,将NSArray
an 桥接到 Swift Array<T>
,您不能只为 a 加上下标CFArray
。
所以你的转换看起来像这样(包装在处理你假设的数组的函数中):
\n\nfunc getIdentity(keychainArray: NSArray) -> SecIdentity? {\n let dict = keychainArray[0] as Dictionary<String,AnyObject>\n let key = kSecImportItemIdentity.takeRetainedValue()\n return dict[key] as SecIdentity?\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n如果你有 a ,CFArray
你可以将它传递给这个函数,它会自动桥接/转换为NSArray
,然后自动转换为 Swift 数组以进行下标。将第 0 项视为 Swift 字典,您可以为字典添加下标以获取恒等式。对于密钥,您需要将其从 an 中取出Unmanaged<CFString>
,因为安全框架未设置用于该常量声明的隐式桥接。
我让这个函数返回一个可选值,因为我不知道您传入的数组+字典是否实际上包含一个标识。如果你确定是这样,你可以去掉两个问号。
\n\n(这在操场上编译,但我没有一个包含字典的数组,该字典包含方便测试的身份,所以买者自负。)
\n