'withUnsafeBytes' is deprecated

Hi. I had the following code in Swift 3 to send a String message using NSStream.


@objcfunc processOutput()
    {
        // Create a message and convert it to data
        let msgToServer = makeMessageToServer()
       
        self.outputBuffer = msgToServer.data(using: .utf8, allowLossyConversion: false)
       
        if self.outputBuffer != nil
        {
            if self.outputBuffer?.count != 0
            {
                let bytesWritten = self.outputBuffer!.withUnsafeBytes
                {
                    self.outputStream!.write($0, maxLength: self.outputBuffer!.count)
                }
               
                if bytesWritten <= 0
                {
                    self.error = self.outputStream?.streamError as NSError?
                }
                   
                else
                {
                    self.outputBuffer?.replaceSubrange(0..<byteswritten, with:="" data())<br="">                }
            }
        }
    }


Now, in Swift 5, I get the following warning in Line 12:


'withUnsafeBytes' is deprecated: use `withUnsafeBytes(_: (UnsafeRawBufferPointer) throws -> R) rethrows -> R` instead


I have read several posts on the topic but still have not figured out how to deal with the wanring in my case.


Your help would be greatly appreciated!

Accepted Reply

IMO the best option here is to replace your stream code with

NWConnection
. It’s a much nicer API to call from Swift.

Failing that, I’ve found it good to isolate this code into an extension on

OutputStream
. For example:
extension OutputStream {

    func write(data: Data) -> Int {
        return data.withUnsafeBytes { buffer -> Int in
            self.write(
                buffer.baseAddress!.assumingMemoryBound(to: UInt8.self),
                maxLength: buffer.count
            )
        }
    }
}

This is tricky to code because the closure consists of a single line, and thus Swift tries to do type inferencing across the entire closure. If there’s a problem with the closure, that type inferencing causes Swift to think that you’re using the deprecated method, and you get confusing errors.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Replies

IMO the best option here is to replace your stream code with

NWConnection
. It’s a much nicer API to call from Swift.

Failing that, I’ve found it good to isolate this code into an extension on

OutputStream
. For example:
extension OutputStream {

    func write(data: Data) -> Int {
        return data.withUnsafeBytes { buffer -> Int in
            self.write(
                buffer.baseAddress!.assumingMemoryBound(to: UInt8.self),
                maxLength: buffer.count
            )
        }
    }
}

This is tricky to code because the closure consists of a single line, and thus Swift tries to do type inferencing across the entire closure. If there’s a problem with the closure, that type inferencing causes Swift to think that you’re using the deprecated method, and you get confusing errors.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks eskimo!


NWConnection looks nice but I need to come up with something quick at the moment.


I tried your second approach extending OutputStream, but, as you expected, get error "Ambiguous use of 'write'". Unfortunately, attempts to fix it are not successful yet.


EDIT: Hm, copying and pasting the code does not work, but typing it in does. Weird!!


Thank you so much for your help, eskimo!