在Swift 2.0中将NSData强制转换为CFDataRef

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)

不要强制转换,使用CFDataCreate() - Larme
我正在尝试这个,必须说我正在学习Swift并且已经使用它工作了8天,我一直在努力组合方法所需的所有参数。CFDataCreate(_ allocator: CFAllocator!, _ bytes: UnsafePointer<UInt8>, _ length: CFIndex) 这相当令人困惑... - Jakub Zak
CFDataCreate(NULL, pkcs12Data.bytes, pkcs12Data.length)?请问需要翻译成中文吗? - Larme
我能理解你为什么自然而然地期望它可以工作。但是它抛出了另一个错误:/Users/user/code/xyz/CryptoOperations/CryptographyOperations/IdentityFileReader.swift:30:42: 无法将类型为“()”的值转换为预期的参数类型“CFAllocator!” - Jakub Zak
然后第二个参数有一个:/Users/user/code/xyz/CryptoOperations/CryptographyOperations/IdentityFileReader.swift:30:66: 不能将类型为 'UnsafePointer<Void>' (即 'UnsafePointer<()>') 的值转换为预期的参数类型 'UnsafePointer<UInt8>' - Jakub Zak
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之类的技术。这使得您的代码在多核计算机上立即具有优势,同时不需要您做太多的工作。
来自文件系统编程指南

6
在Swift 4中,您应该这样做: 但是,在Xcode 9.2中,当两个可选项放在同一个子句中时,它似乎会自动将视为。 我必须将这两个可选项放在不同的子句中,如下所示:
//        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

4

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接