2016-06-29 34 views
8

La soluzione di this question non funziona più con Swift 3.scrivono dati su una NSOutputStream a Swift 3

Non c'è più una proprietà bytes di Data (ex NSData.

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

Con questo codice, ottengo l'errore:

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

Come si può scrivere Data a un NSOutputStream in Swift 3?

risposta

10

NSData aveva una struttura bytes per accedere ai byte. Il nuovo tipo di valore Data in Swift 3 ha invece un metodo , che chiama una chiusura con un puntatore ai byte.

Quindi questo è come si scrive Data a un NSOutputStream (senza fusione a NSData):

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

Note: withUnsafeBytes() è un metodo generico:

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

Nella chiamata sopra, sia ContentType e ResultType vengono automaticamente dedotto dalla compilatore (come UInt8 e Int), rendendo aggiuntivi UnsafePointer() conversioni inutili.

outputStream.write() restituisce il numero di byte effettivamente scritto. Generalmente, è necessario il controllare il valore. Può essere -1 se l'operazione di scrittura non è riuscita o inferiore a data.count quando si scrive in socket, pipe o altri oggetti con un controllo di flusso.

0

Data e NSData sono due classi separate in Swift 3 e non ha la proprietà bytes.

La soluzione è definire data come di tipo NSData

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

Secondo 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, grazie per la risposta. Era una base per una soluzione completa.Eccolo:

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

Basta utilizzare questa estensione (Swift 4)

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

E per InputStream

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