ios - 仅将 4 行代码从 objective-c 转换为 swift(指针)

标签 ios objective-c pointers swift

两天以来,我一直在将一段代码从 Objective-C 翻译成 Swift:

CFArrayRef keyref = NULL;
CFDictionaryRef identityDict = CFArrayGetValueAtIndex(keyref, 0);
SecIdentityRef identityRef = (SecIdentityRef)CFDictionaryGetValue(identityDict,      kSecImportItemIdentity);

是的,就是这样!我根本无法用这些指针满足编译器的要求。 请帮助:-)

这是要翻译的整个 Objective-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);

这就是我到目前为止所得到的:

// 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)

问题开始于:

var identityDict: CFDictionary = CFArrayGetValueAtIndex(keyref, 0)

错误:“非托管 CFArray 不可转换为 CFArray”。

这是我迄今为止最好的尝试。

最佳答案

大概第一行是实际数组的占位符?如果您实际上正在使用 NULL数组指针,其余代码什么都不做。

假设您从真实的 CFArrayRef 开始,您可以利用桥接:CoreFoundation 类型自动被视为 Swift 对象,因此您无需使用 CFArrayRefCFDictionaryRef指针。这同样适用于任何其他使用 CF 类型系统的 C API,因此它也应该适用于 SecIdentity .

CF 集合的自动桥接似乎有些奇怪 — 您可以隐式桥接 CFArrayNSArray和一个 NSArray到 swift Array<T> , 你不能只下标 CFArray .

因此您的转换看起来像这样(包装在处理您假设的数组的函数中):

func getIdentity(keychainArray: NSArray) -> SecIdentity? {
    let dict = keychainArray[0] as Dictionary<String,AnyObject>
    let key = kSecImportItemIdentity.takeRetainedValue()
    return dict[key] as SecIdentity?
}

如果你有一个 CFArray你可以将它传递给这个函数,它会自动桥接/转换到 NSArray ,然后自动转换为 Swift 数组以进行下标。将项目 0 视为 Swift 字典,您可以下标字典以获取标识。对于 key ,您需要将其从 Unmanaged<CFString> 中取出因为安全框架未设置为隐式桥接该常量声明。

我让这个函数返回一个可选的,因为我不知道你传入的数组+字典是否真的包含一个标识。如果你确定是,你可以去掉两个问号。

(这可以在 playground 中编译,但我没有一个包含字典的数组,该字典包含便于测试的身份,所以请注意买空者。)

关于ios - 仅将 4 行代码从 objective-c 转换为 swift(指针),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24111059/

相关文章:

ios - clang_complete : Vim autocompletion for iOS

ios - `OpaqueJSValue`中的 `JavaScriptCore`从哪里来?

ios - 使用旧版 Swift 构建的应用程序能否在应用程序商店中无限期存在?

objective-c - 三元条件运算符中的赋值产生 “Expression is not assignable”错误

c++ - 是否可以覆盖指向 C++ 中对象的指针的数组访问运算符?

c++ - 以类型安全的方式将指针转换为指针

c - 该程序仅解决第一行[数独]

ios - 如何设置 NSPopupButton 菜单项的颜色

objective-c - 为什么 (int)[ @"-1"floatValue] 不返回 -1

iphone - 可滚动位置后窗口的背面