11

这个问题的解决方案不再适用于 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'

你怎么能DataNSOutputStreamSwift 3 中写信?

4

4 回答 4

17

NSData具有bytes访问字节的属性。Swift 3 中的新Data值类型有一个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器会自动推断出 和 (作为UInt8Int),因此 UnsafePointer()不需要额外的转换。

outputStream.write()返回实际写入的字节数。通常,您应该检查该值。-1如果写入操作失败,或者data.count写入套接字、管道或其他具有流控制的对象时失败,则可能会失败。

于 2016-06-29T06:53:47.970 回答
11

只需使用此扩展程序:

斯威夫特 5

extension OutputStream {
  func write(data: Data) -> Int {
    return data.withUnsafeBytes {
      write($0.bindMemory(to: UInt8.self).baseAddress!, maxLength: data.count)
    }
  }
}

对于 InputStream

extension InputStream {
  func read(data: inout Data) -> Int {
    return data.withUnsafeMutableBytes {
      read($0.bindMemory(to: UInt8.self).baseAddress!, maxLength: data.count)
    }
  }
}

斯威夫特 4

extension OutputStream {
  func write(data: Data) -> Int {
    return data.withUnsafeBytes { write($0, maxLength: data.count) }
  }
}
extension InputStream {
  func read(data: inout Data) -> Int {
    return data.withUnsafeMutableBytes { read($0, maxLength: data.count) }
  }
}
于 2017-09-19T13:31:06.827 回答
8

马丁 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
    }
}
于 2016-09-19T18:34:35.443 回答
0

DataandNSData是 Swift 3 中的两个单独的类,并且Data没有bytes属性。

解决方案是定义data为类型NSData

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

根据从 Swift 2.2 迁移到 Swift 2.3 或 Swift 3

迁移器会将 NSData 的大多数用途转换为新的值类型 Data。但是,NSData 上有某些方法对 UnsafeMutablePointer 进行操作,而 Data 上的相应方法使用 UnsafeMutablePointer。(例如,NSData.getBytes( :length:) 比 Data.copyBytes( :length:) 更容易接受。)提醒一下,Swift 类型的内存布局并不能保证。

于 2016-06-29T04:28:27.493 回答