La solution de cette question ne fonctionne plus avec Swift 3.
Il n'y a plus de propriété bytes
de Data
(anciennement NSData
.
let data = dataToWrite.first!
self.outputStream.write(&data, maxLength: data.count)
Avec ce code, j'obtiens l'erreur:
Cannot convert value of type 'Data' to expected argument type 'UInt8'
Comment pouvez-vous écrire Data
dans NSOutputStream
dans Swift 3?
NSData
avait une propriété bytes
pour accéder aux octets. Le nouveau type de valeur Data
dans Swift 3 utilise à la place une méthode withUnsafeBytes()
, qui appelle une fermeture avec un pointeur sur les octets.
Voici comment vous écrivez Data
en NSOutputStream
(Sans transtypage en NSData
):
let data = ... // a Data value
let bytesWritten = data.withUnsafeBytes { outputStream.write($0, maxLength: data.count) }
Remarques: withUnsafeBytes()
est une méthode générique:
/// Access the bytes in the data.
///
/// - warning: The byte pointer argument should not be stored and used outside of the lifetime of the call to the closure.
public func withUnsafeBytes<ResultType, ContentType>(_ body: @noescape (UnsafePointer<ContentType>) throws -> ResultType) rethrows -> ResultType
Dans l'appel ci-dessus, ContentType
et ResultType
sont automatiquement déduits par Le compilateur (en tant que UInt8
et Int
), ce qui rend inutiles les conversions supplémentaires de UnsafePointer()
.
outputStream.write()
renvoie le nombre d'octets réellement écrits. En règle générale, vous devriez vérifier cette valeur. Ce peut être -1
si L’opération d’écriture a échoué, ou inférieur à data.count
lorsqu’il écrit Sur des sockets, des pipes ou d’autres objets dotés d’un contrôle de flux.
Martin R , merci pour votre réponse. C'était la base d'une solution complète. C'est ici:
extension OutputStream {
/// Write String to outputStream
///
/// - parameter string: The string to write.
/// - parameter encoding: The String.Encoding to use when writing the string. This will default to UTF8.
/// - parameter allowLossyConversion: Whether to permit lossy conversion when writing the string.
///
/// - returns: Return total number of bytes written upon success. Return -1 upon failure.
func write(_ string: String, encoding: String.Encoding = String.Encoding.utf8, allowLossyConversion: Bool = true) -> Int {
if let data = string.data(using: encoding, allowLossyConversion: allowLossyConversion) {
var bytesRemaining = data.count
var totalBytesWritten = 0
while bytesRemaining > 0 {
let bytesWritten = data.withUnsafeBytes {
self.write(
$0.advanced(by: totalBytesWritten),
maxLength: bytesRemaining
)
}
if bytesWritten < 0 {
// "Can not OutputStream.write(): \(self.streamError?.localizedDescription)"
return -1
} else if bytesWritten == 0 {
// "OutputStream.write() returned 0"
return totalBytesWritten
}
bytesRemaining -= bytesWritten
totalBytesWritten += bytesWritten
}
return totalBytesWritten
}
return -1
}
}
Il suffit d'utiliser cette extension (Swift 4)
extension OutputStream {
func write(data: Data) -> Int {
return data.withUnsafeBytes { write($0, maxLength: data.count) }
}
}
Et pour InputStream
extension InputStream {
func read(data: inout Data) -> Int {
return data.withUnsafeMutableBytes { read($0, maxLength: data.count) }
}
}
Data
et NSData
sont deux classes distinctes dans Swift 3, et Data
ne possède pas la propriété bytes
.
La solution consiste à définir data
comme étant de type NSData
let data: NSData = dataToWrite.first!
self.outputStream.write(UnsafePointer<UInt8>(data.bytes), maxLength: data.length)
SelonMigration vers Swift 2.3 ou Swift 3 à partir de Swift 2.2:
Le migrateur convertira la plupart des utilisations de NSData vers le nouveau type de valeur Data. Cependant, il existe certaines méthodes sur NSData qui fonctionnent sur UnsafeMutablePointer, tandis que les méthodes correspondantes sur Data utilisent UnsafeMutablePointer. (Par exemple, NSData.getBytes (: length :) est plus acceptable que Data.copyBytes (: length :).) Pour rappel, la disposition en mémoire des types Swift n'est pas garantie.