2016-06-29 2 views
8

Решение this question больше не работает с Swift 3.Запись данных на NSOutputStream в Swift 3

Там больше не свойство bytes из Data (ранее NSData.

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

С помощью этого кода, Я получаю ошибку:

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

Как вы можете написать Data к NSOutputStream в Swift 3?

ответ

10

NSData имел bytes свойство для доступа к байтам. Новый тип значения Data в Swift 3 вместо этого имеет метод withUnsafeBytes() , который вызывает замыкание с указателем на байты.

Так вот как вы пишете Data к NSOutputStream (без приведения к NSData):

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

Примечания: withUnsafeBytes() является общим методом:

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

В приведенном выше вызове как ContentType и ResultType автоматически выводится на компилятор (как это UInt8 и Int), что делает дополнительные UnsafePointer() преобразования ненужным.

outputStream.write() возвращает количество фактически записанных байтов. Как правило, вы должны проверить это значение. Это может быть -1, если операция записи не удалась или меньше data.count при записи в розетки, трубы или другие объекты с управлением потоком.

0

Data и NSData - это два отдельных класса в Swift 3, а Data не имеет bytes.

Решение состоит в определении data как типа NSData

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

Согласно 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, благодарю вас за ответ. Это стало основой для полного решения.Вот оно:

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

Просто используйте это расширение (Swift 4)

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

И для InputStream

extension InputStream { 
    func read(data: inout Data) -> Int { 
    return data.withUnsafeMutableBytes { read($0, maxLength: data.count) } 
    } 
} 
Смежные вопросы