Swift 5.0:'withUnsafeBytes' 已弃用:使用 `withUnsafeBytes<R>(...)
Swift 5.0: 'withUnsafeBytes' is deprecated: use `withUnsafeBytes<R>(...)
我之前在Swift4.2中使用过这段代码来生成一个id:
public static func generateId() throws -> UInt32 {
let data: Data = try random(bytes: 4)
let value: UInt32 = data.withUnsafeBytes { [=13=].pointee } // deprecated warning!
return value // + some other stuff
}
withUnsafeBytes
在 Swift 5.0 中已弃用。我该如何解决这个问题?
在 Swift 5 中,Data
的 withUnsafeBytes()
方法使用(未类型化的)UnsafeRawBufferPointer
调用闭包,您可以 load()
来自原始内存:
let value = data.withUnsafeBytes { [=10=].load(as: UInt32.self) }
(比较How to use Data.withUnsafeBytes in a well-defined manner? in the Swift forum). Note that this requires that the memory is aligned on a 4-byte boundary. For alternatives see .
另请注意,从 Swift 4.2 开始,您可以简单地使用新的 Random
API:
创建一个随机的 32 位整数
let randomId = UInt32.random(in: .min ... .max)
在 Xcode 10.2、Swift 5 上,使用 [=13=].load(as:)
对我不起作用,无论是从指针读取还是写入指针。
相反,使用 [=14=].baseAddress?.assumingMemoryBound(to:)
似乎效果不错。
从指针缓冲区读取示例(代码与问题无关):
var reachability: SCNetworkReachability?
data.withUnsafeBytes { ptr in
guard let bytes = ptr.baseAddress?.assumingMemoryBound(to: Int8.self) else {
return
}
reachability = SCNetworkReachabilityCreateWithName(nil, bytes)
}
写入缓冲区指针的示例(代码与问题无关):
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
}
}
问题中的代码如下所示:
let value = data.withUnsafeBytes {
[=12=].baseAddress?.assumingMemoryBound(to: UInt32.self)
}
在 'withUnsafeBytes' is deprecated: use withUnsafeBytes<R>(…)
警告持续存在的情况下,似乎 the compiler can get confused when the closure has only one line。使闭包有两行或更多行可能会消除歧义。
我在尝试找出压缩流教程时遇到了这个错误。为了让它工作,我添加了一个将原始缓冲区指针转换为 UnsafePointer
的步骤
我正在编写的教程中的原始代码。
--> 其中输入:数据
--> 其中流:compression_stream
//Method that shows the deprecation alert
return input.withUnsafeBytes { (srcPointer: UnsafePointer<UInt8>) in
//holder
var output = Data()
//Source and destination buffers
stream.src_ptr = srcPointer //UnsafePointer<UInt8>
stream.src_size = input.count
… etc.
}
带有转换的代码,使上面的代码可以使用有效的方法
return input.withUnsafeBytes { bufferPtr in
//holder
var output = Data()
//Get the Raw pointer at the initial position of the UnsafeRawBuffer
let base: UnsafeRawPointer? = bufferPtr.baseAddress
//Unwrap (Can be combined with above, but kept it separate for clarity)
guard let srcPointer = base else {
return output
}
//Bind the memory to the type
let count = bufferPtr.count
let typedPointer: UnsafePointer<UInt8> = srcPointer.bindMemory(to: UInt8.self, capacity: count)
// Jump back into the original method
stream.src_ptr = typedPointer //UnsafePointer<UInt8>
}
修复此警告的另一种方法是使用 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)
}
我之前在Swift4.2中使用过这段代码来生成一个id:
public static func generateId() throws -> UInt32 {
let data: Data = try random(bytes: 4)
let value: UInt32 = data.withUnsafeBytes { [=13=].pointee } // deprecated warning!
return value // + some other stuff
}
withUnsafeBytes
在 Swift 5.0 中已弃用。我该如何解决这个问题?
在 Swift 5 中,Data
的 withUnsafeBytes()
方法使用(未类型化的)UnsafeRawBufferPointer
调用闭包,您可以 load()
来自原始内存:
let value = data.withUnsafeBytes { [=10=].load(as: UInt32.self) }
(比较How to use Data.withUnsafeBytes in a well-defined manner? in the Swift forum). Note that this requires that the memory is aligned on a 4-byte boundary. For alternatives see
另请注意,从 Swift 4.2 开始,您可以简单地使用新的 Random
API:
let randomId = UInt32.random(in: .min ... .max)
在 Xcode 10.2、Swift 5 上,使用 [=13=].load(as:)
对我不起作用,无论是从指针读取还是写入指针。
相反,使用 [=14=].baseAddress?.assumingMemoryBound(to:)
似乎效果不错。
从指针缓冲区读取示例(代码与问题无关):
var reachability: SCNetworkReachability?
data.withUnsafeBytes { ptr in
guard let bytes = ptr.baseAddress?.assumingMemoryBound(to: Int8.self) else {
return
}
reachability = SCNetworkReachabilityCreateWithName(nil, bytes)
}
写入缓冲区指针的示例(代码与问题无关):
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
}
}
问题中的代码如下所示:
let value = data.withUnsafeBytes {
[=12=].baseAddress?.assumingMemoryBound(to: UInt32.self)
}
在 'withUnsafeBytes' is deprecated: use withUnsafeBytes<R>(…)
警告持续存在的情况下,似乎 the compiler can get confused when the closure has only one line。使闭包有两行或更多行可能会消除歧义。
我在尝试找出压缩流教程时遇到了这个错误。为了让它工作,我添加了一个将原始缓冲区指针转换为 UnsafePointer
的步骤我正在编写的教程中的原始代码。
--> 其中输入:数据
--> 其中流:compression_stream
//Method that shows the deprecation alert
return input.withUnsafeBytes { (srcPointer: UnsafePointer<UInt8>) in
//holder
var output = Data()
//Source and destination buffers
stream.src_ptr = srcPointer //UnsafePointer<UInt8>
stream.src_size = input.count
… etc.
}
带有转换的代码,使上面的代码可以使用有效的方法
return input.withUnsafeBytes { bufferPtr in
//holder
var output = Data()
//Get the Raw pointer at the initial position of the UnsafeRawBuffer
let base: UnsafeRawPointer? = bufferPtr.baseAddress
//Unwrap (Can be combined with above, but kept it separate for clarity)
guard let srcPointer = base else {
return output
}
//Bind the memory to the type
let count = bufferPtr.count
let typedPointer: UnsafePointer<UInt8> = srcPointer.bindMemory(to: UInt8.self, capacity: count)
// Jump back into the original method
stream.src_ptr = typedPointer //UnsafePointer<UInt8>
}
修复此警告的另一种方法是使用 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)
}