将 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: UnsafePointerCFDataCreate(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?