将 NSData 转换为! swift 2.0 中的 CFDataRef

Posted

技术标签:

【中文标题】将 NSData 转换为! swift 2.0 中的 CFDataRef【英文标题】:Cast NSData as! CFDataRef in swift 2.0 【发布时间】:2015-10-01 08:50:55 【问题描述】:

我的代码中有一行已被弃用,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() 我正在尝试,我必须说我正在学习 swift 并使用它第 8 天,我正在努力将方法所需的所有参数放在一起。 CFDataCreate(_ allocator: CFAllocator!, _ bytes: UnsafePointer, _ length: CFIndex) 相当混乱... CFDataCreate(NULL, pkcs12Data.bytes, pkcs12Data.length)? 嗯,我明白你为什么自然会期望它起作用。但是它会引发另一个错误:/Users/user/code/xyz/CryptoOperations/CryptographyOperations/IdentityFileReader.swift:30:42: Cannot convert value of type '()' to expected argument type 'CFAllocator!' 然后第二个参数还有一个:/Users/user/code/xyz/CryptoOperations/CryptographyOperations/IdentityFileReader.swift:30:66: Cannot convert value of type 'UnsafePointer<Void>' (aka 'UnsafePointer<()>') to expected argument type 'UnsafePointer<UInt8>' 【参考方案1】:

稍微安全一点的版本:

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

【讨论】:

【参考方案2】:

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

Xcode 9.2 似乎自动将 NSData 视为 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

【讨论】:

【参考方案3】:

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

【讨论】:

以上是关于将 NSData 转换为! swift 2.0 中的 CFDataRef的主要内容,如果未能解决你的问题,请参考以下文章

将UIImage转换为NSData并在Swift中转换回UIImage?

将 NSData Objective-C 代码转换为 Swift 时遇到问题

将 NSData 转换为 JSON 对象数组

如何在 Swift 3 中将 NSData 转换为数据?

NSArray怎么转换为NSData

在 Swift 中从 NSString 创建 NSData