5

我的代码中有一行已被弃用,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)
4

3 回答 3

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 等技术。这使您的代码在多核计算机上具有立竿见影的优势,同时不需要您做很多工作。

来自文件系统编程指南

于 2015-10-01T09:38:44.880 回答
5

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

当两个可选项放在同一个子句中时, Xcode 9.2 似乎自动将其NSData视为。我必须将这两个选项放在单独的子句中,如下所示:Dataguard-letguard-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
于 2018-02-03T04:47:17.257 回答
4

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

于 2015-11-19T03:46:20.773 回答