仅将4行代码从目标c转换为swift(指针) [英] Translate just 4 lines of code from objective c to swift (Pointers)

查看:79
本文介绍了仅将4行代码从目标c转换为swift(指针)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

两天以来,我一直无法完成将目标代码从Objective-C转换为Swift的工作:

I have been stuck since two days translating a piece of code from Objective-C to Swift:

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

是的,仅此而已!我根本无法用那些指针满足编译器的要求. 请帮忙:-)

Yes, that's all! I simply can't satisfy the compiler with those pointers. Please help :-)

这是要翻译的整个目标c代码:

This is the whole objective c code to translate:

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

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

And this is what i got so far:

// 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".

Error: "unmanaged CFArray not convertible to CFArray".

到目前为止,这是我最好的尝试.

This is my best try so far.

推荐答案

大概第一行是实际数组的占位符吗?如果您实际上是在使用NULL数组指针,则其余代码将不执行任何操作.

Presumably the first line is a placeholder for an actual array? If you're actually working with a NULL array pointer, the rest of your code does nothing.

假设您从一个真正的CFArrayRef开始,则可以利用桥接的优势:CoreFoundation类型会像Swift对象一样被自动对待,因此您不需要使用CFArrayRefCFDictionaryRef指针.对于使用CF类型系统的任何其他C API,也是如此,因此它也应适用于SecIdentity.

Assuming you're starting from a real CFArrayRef, you can take advantage of bridging: CoreFoundation types are automatically treated like Swift objects, so you don't need to work with CFArrayRef and CFDictionaryRef pointers. The same goes for any other C API that uses the CF type system, so it should also apply to SecIdentity.

自动收集CF集合似乎有些怪异-您可以将CFArray隐式连接到NSArray,将NSArray隐式连接到Swift Array<T>,您不能仅对.

There seems to be some weirdness with automatic bridging of CF collections — you can implicitly bridge a CFArray to an NSArray and an NSArray to a Swift Array<T>, you can't just subscript a CFArray.

所以您的转换看起来像这样(包装在处理您假定的数组的函数中):

So your conversion looks something like this (wrapped in a function that handles your assumed array):

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字典,您可以对字典下标以获取标识.对于密钥,您需要将其从Unmanaged<CFString>中拉出,因为没有为该常量的声明的隐式桥接设置安全框架.

If you have a CFArray you can pass it to this function and it'll automatically bridge/cast to NSArray, which then automatically casts to a Swift array for subscripting. Treat item 0 as a Swift dictionary, and you can subscript the dictionary to get the identity out. For the key, you'll need to pull it out of an Unmanaged<CFString> because the Security framework isn't set up for implicit bridging of that constant's declaration.

我离开了这个函数返回一个可选的函数,因为我不知道您要传入的array + dictionary是否实际上包含一个标识.如果确定可以,则可以删除两个问号.

I've left this function returning an optional, since I don't know wether the array+dictionary you're passing in actually contains an identity. If you're sure it does, you could take out the two question marks.

(它在操场上编译,但是我没有一个包含字典的数组,该字典包含一个方便测试的标识,因此 caveat emptor .)

(This compiles in playground, but I don't have an array containing a dictionary containing an identity handy for testing with, so caveat emptor.)

这篇关于仅将4行代码从目标c转换为swift(指针)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆