将NSData转换为! swift 2.0中的CFDataRef

时间:2015-10-01 08:50:56

标签: ios casting swift2 nsdata cfdata

我在代码中有一行被弃用了,在XCode中有什么建议要替换它,但我无法理解差异,这些是我的三行有效:

let path = NSBundle.mainBundle().pathForResource("example", ofType: ".p12")
let pkcs12Data = NSData.dataWithContentsOfMappedFile(path!)
let cf: CFDataRef = pkcs12Data as! CFDataRef

现在根据警告和建议我将我的代码更改为:

let path = NSBundle.mainBundle().pathForResource("example", ofType: ".p12")
let pkcs12Data = NSData(contentsOfFile: path!)
let cf: CFDataRef = pkcs12Data as! CFDataRef

这给了我一个错误:

EXC_BAD_INSTRUCTION (CODE=EXC_I386_INVOP SUBCODE=0x0)

3 个答案:

答案 0 :(得分:10)

更安全的版本:

guard
    let url = NSBundle.mainBundle().URLForResource("example", withExtension: ".p12"),
    let data = NSData(contentsOfURL: url)
    else { // Do something because you couldn't get the file or convert it to NSData }

    let dataPtr = CFDataCreate(kCFAllocatorDefault, UnsafePointer<UInt8>(data.bytes), data.length)

注意,使用基于文件的URL而不是字符串路径。

  

在决定调用哪些例程时,选择允许您使用NSURL对象指定路径的路径,而不是使用字符串指定路径的路径。大多数基于URL的例程都是在OS X v10.6及更高版本中引入的,并且从一开始就设计为利用Grand Central Dispatch等技术。这使您的代码在多核计算机上立即获得优势,同时不需要您做太多工作。

来自File System Programming Guide

答案 1 :(得分:4)

@ Abizern的答案是有效的,但使用CFDataCreateWithBytesNoCopy代替CFDataCreate更有效。

答案 2 :(得分:3)

然而,在Swift 4中,你应该这样做:

当两个选项放在同一个NSData子句中时,Xcode 9.2似乎会自动将Data视为guard-let。 我必须将两个选项放在单独的guard-let子句中,如下所示:

//        guard let url = Bundle.main.url(forResource: "example", withExtension: ".p12"),
//            let data = NSData(contentsOf: url) else {
//            return
//        }

guard let url = Bundle.main.url(forResource: "example", withExtension: ".p12") else {
    return
}
guard let data = NSData(contentsOf: url) else {
    return
}
let bytes = data.bytes.assumingMemoryBound(to: UInt8.self)
let cfData = CFDataCreate(kCFAllocatorDefault, bytes, data.length) // CFData object you want