В ролях NSData как! CFDataRef в Swift 2.0

У меня есть строка в коде, которая устарела, в 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 ответа

Решение

Немного безопаснее версия:

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. Это дает вашему коду непосредственное преимущество на многоядерных компьютерах, не требуя от вас много работы.

Из руководства по программированию файловой системы

В 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

@Abizern ответ работает, но используйте CFDataCreateWithBytesNoCopy вместо CFDataCreate более эффективно.

Другие вопросы по тегам