WebberLai WebberLai - 4 months ago 114
Swift Question

How to make sure the output stream is write success in swift?

I just try to write a sample about Bonjour service and a simple socket I/O stream .

Here is my sample link

https://github.com/WebberLai/SwiftBonjourSocket

or git url:

https://github.com/WebberLai/SwiftBonjourSocket.git

And this what can I do now

1.Publish a service and scan the service .
2.Create a I/O stream socket between two devices or simulator

I got some problem when after the socket is connected , I try to send some text to service.
And this the code I use to send text to service

@IBAction func sendMessage(sender:AnyObject!){

if (self.outputStream == nil){
print("Connection not create yet ! =====> Return")
return
}

let s : String = (self.textfield?.text)!

print("\(self.outputStream) ==> Pass Data : \(s)")

let data: NSData = s.data(using: String.Encoding.utf8)!

self.outputStream?.open()
self.outputStream?.write(UnsafePointer<UInt8>(data.bytes), maxLength: data.length)
self.outputStream?.close()
//Service no any response or log
}


And I press the button ,seems nothing happen , I was wonder does it write success or not ?

/********* UPDATE **********/
The problem about received side , need add run loop

so the code will looks like this

func netService(_ sender: NetService, didAcceptConnectionWith inputStream: InputStream, outputStream: NSOutputStream) {

self.receiveTextView?.text = "Accept Connection Success"

print("netService : \(sender) didAcceptConnectionWith Input Stream : \(inputStream) , Output Stream : \(outputStream)")
inputStream.delegate = self
outputStream.delegate = self
inputStream.schedule(in: RunLoop.main(), forMode: RunLoopMode.defaultRunLoopMode)
outputStream.schedule(in: RunLoop.main(), forMode: RunLoopMode.defaultRunLoopMode)
inputStream.open()
outputStream.open()
}


And you will receive the data in Stream delegate

func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
case Stream.Event.hasBytesAvailable:

NSLog("HasBytesAvailable")

var buffer = [UInt8](repeating:0, count:4096)

let inputStream = aStream as? InputStream

while ((inputStream?.hasBytesAvailable) != false){
let len = inputStream?.read(&buffer, maxLength: buffer.count)
if(len > 0){
let output = NSString(bytes: &buffer, length: buffer.count, encoding: String.Encoding.utf8.rawValue)
if (output != ""){
NSLog("Server Received : %@", output!)
self.receiveTextView?.text = output as String?
}
}else{
break
}
}
break
default:
NSLog("unknown.")
}


}

Answer

Assuming you know that the sendMessage(_:) method is getting called and all you're looking to do is check whether or not the write was successful, this can be done in a straight forward way by looking at the return value of the write method (documentation) Here's a quick example.

@IBAction func sendMessage(sender: AnyObject!) {
    guard let outputStream = outputStream else {
        print("Connection not create yet ! =====> Return")
        return
    }

    guard let text = textfield?.text,
        data: NSData = text.data(using: String.Encoding.utf8) else {
            print("no data")
            return
    }

    print("\(outputStream) ==> Pass Data : \(text)")
    outputStream.open()
    defer {
        outputStream.close()
    } 

    let result = outputStream.write(UnsafePointer<UInt8>(data.bytes), maxLength: data.length)
    if result == 0 {
        print("Stream at capacity")
    } else if result == -1 {
        print("Operation failed: \(outputStream.streamError)")
    } else {
        print("The number of bytes written is \(result)")
    }
}