2016-06-29 3 views
8

Die Lösung von this question funktioniert nicht mehr mit Swift 3.Schreiben von Daten auf ein NSOutputStream in Swift 3

Es ist nicht mehr eine Eigenschaft bytes von Data (früher NSData.

let data = dataToWrite.first! 
self.outputStream.write(&data, maxLength: data.count) 

Mit diesem Code, ich erhalte den Fehler:

Cannot convert value of type 'Data' to expected argument type 'UInt8' 

Wie kann man schreiben Data zu einem NSOutputStream in Swift 3?

Antwort

10

NSData hatte eine bytes Eigenschaft die Bytes zuzugreifen. Der neue Wert Data in Swift 3 hat stattdessen eine Methode withUnsafeBytes() , die eine Schließung mit einem Zeiger auf die Bytes aufruft.

Das ist also, wie Sie schreiben Data zu einem NSOutputStream (ohne NSData zu Gießen):

let data = ... // a Data value 
let bytesWritten = data.withUnsafeBytes { outputStream.write($0, maxLength: data.count) } 

Bemerkungen: withUnsafeBytes() ist eine generische Methode:

/// 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 

In dem obigen Anruf sowohl ContentType als auch ResultType werden automatisch vom Compiler abgeleitet (wie UInt8 und Int), was zusätzliche UnsafePointer() Konvertierungen überflüssig macht.

outputStream.write() gibt die Anzahl der tatsächlich geschriebenen Bytes zurück. Im Allgemeinen sollten Sie überprüfen diesen Wert. Es kann -1 sein, wenn der Schreibvorgang fehlgeschlagen ist, oder weniger als data.count beim Schreiben auf Sockets, Pipes oder andere Objekte mit einer Ablaufsteuerung.

0

Data und NSData sind zwei getrennte Klassen in Swift 3 und Data hat nicht die bytes Eigenschaft.

Die Lösung ist data zu definieren, wie der Art ist, NSData

let data: NSData = dataToWrite.first! 
self.outputStream.write(UnsafePointer<UInt8>(data.bytes), maxLength: data.length) 

Nach Migrating to Swift 2.3 or Swift 3 from Swift 2.2:

The migrator will convert most uses of NSData to the new value type Data. However, there are certain methods on NSData that operate on UnsafeMutablePointer, while the corresponding methods on Data use UnsafeMutablePointer. (For example, NSData.getBytes(:length:) is more accepting than Data.copyBytes(:length:).) As a reminder, the in-memory layout of Swift types is not guaranteed.

3

Martin R, danke für Ihre Antwort. Das war die Grundlage für eine Komplettlösung.Hier ist sie:

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 
    } 
} 
2

Gerade diese Erweiterung (Swift 4)

extension OutputStream { 
    func write(data: Data) -> Int { 
    return data.withUnsafeBytes { write($0, maxLength: data.count) } 
    } 
} 

Und für Input

extension InputStream { 
    func read(data: inout Data) -> Int { 
    return data.withUnsafeMutableBytes { read($0, maxLength: data.count) } 
    } 
}