私は以前にこのコードをSwift 4.2で使用してIDを生成しました:
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
はSwift 5.0で非推奨になりました。これを解決するにはどうすればよいですか?
Swift 5では、Data
のwithUnsafeBytes()
メソッドは、(型なし)UnsafeRawBufferPointer
でクロージャを呼び出し、次のことができます load()
生のメモリからの値:
let value = data.withUnsafeBytes { $0.load(as: UInt32.self) }
(比較 明確に定義された方法でData.withUnsafeBytesを使用する方法? Swiftフォーラム)。これには、メモリがaligned4バイト境界。代替案については、 往復Swiftデータとの数値型 を参照してください。
Swift 4.2以降では、新しい Random
API を使用して32ビット整数をランダムに作成できることに注意してください。
let randomId = UInt32.random(in: .min ... .max)
Xcode 10.2では、Swift 5、$0.load(as:)
の使用は、ポインターからの読み取り時も書き込み時も機能しませんでした。
代わりに、$0.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 {
$0.baseAddress?.assumingMemoryBound(to: UInt32.self)
}
_
'withUnsafeBytes' is deprecated: use withUnsafeBytes<R>(…)
警告が続く場合、 クロージャーが1行しかないとコンパイラーが混乱する可能性があります のようです。クロージャを2行以上にすることで、あいまいさがなくなる場合があります。
この警告を修正してbindMemory(to:)を使用するもう1つの方法。
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)
}
圧縮ストリームのチュートリアルを理解しようとしたときに、このエラーが発生しました。それを機能させるために、生のバッファポインタを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>
}