Anteriormente usé este código en Swift 4.2 para generar una identificación:
public static func generateId() throws -> UInt32 { let data: Data = try random(bytes: 4) let value: UInt32 = data.withUnsafeBytes { $0.pointee } // deprecated warning! return value // + some other stuff }
withUnsafeBytes
está obsoleto en Swift 5.0. ¿Como puedo resolver esto?
En Swift 5, el método withUnsafeBytes()
de Data
llama al cierre con un UnsafeRawBufferPointer
(sin tipo), y puede load()
el valor de la memoria sin procesar:
let value = data.withUnsafeBytes { $0.load(as: UInt32.self) }
(compare ¿Cómo usar Data.withUnsafeBytes de una manera bien definida? en el foro de Swift). Tenga en cuenta que esto requiere que la memoria esté alineada en un límite de 4 bytes. Para ver alternativas, consulte los tipos de números Swift de ida y vuelta a/desde datos .
Tenga en cuenta también que a partir de Swift 4.2 puede crear un número entero aleatorio de 32 bits simplemente usando la nueva API Random
:
let randomId = UInt32.random(in: .min ... .max)
En Xcode 10.2, Swift 5, usar $0.load(as:)
no funcionó para mí, tanto al leer desde el puntero como al escribir en él.
En cambio, usar $0.baseAddress?.assumingMemoryBound(to:)
parece funcionar bien.
Ejemplo de lectura del búfer de puntero (el código no está relacionado con la pregunta):
var reachability: SCNetworkReachability? data.withUnsafeBytes { ptr in guard let bytes = ptr.baseAddress?.assumingMemoryBound(to: Int8.self) else { return } reachability = SCNetworkReachabilityCreateWithName(nil, bytes) }
Ejemplo de escritura en el puntero del búfer (el código no está relacionado con la pregunta):
try outputData.withUnsafeMutableBytes { (outputBytes: UnsafeMutableRawBufferPointer) in let status = CCKeyDerivationPBKDF(CCPBKDFAlgorithm(kCCPBKDF2), passphrase, passphrase.utf8.count, salt, salt.utf8.count, CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA1), rounds, outputBytes.baseAddress?.assumingMemoryBound(to: UInt8.self), kCCKeySizeAES256) guard status == kCCSuccess else { throw Error.keyDerivationError } }
El código de la pregunta se vería así:
let value = data.withUnsafeBytes { $0.baseAddress?.assumingMemoryBound(to: UInt32.self) }
En los casos en que la 'withUnsafeBytes' is deprecated: use withUnsafeBytes<R>(…)
persiste, parece que el compilador puede confundirse cuando el cierre tiene solo una línea . Hacer que el cierre tenga dos o más líneas podría eliminar la ambigüedad.
Una forma más de corregir esta advertencia para usar bindMemory(to:) .
var rawKey = Data(count: rawKeyLength) let status = rawKey.withUnsafeMutableBytes { rawBytes -> Int32 in guard let rawBytes = rawBytes.bindMemory(to: UInt8.self).baseAddress else { return Int32(kCCMemoryFailure) } return CCSymmetricKeyUnwrap(alg, ivBytes, iv.count, keyBytes, key.count, wrappedKeyBytes, wrappedKey.count, rawBytes, &rawKeyLength) }