CFStreamCreatePairWithSocketToHost crashes unexpectedly with Swift

3.3k Views Asked by At

Finally time to ask my first question here!

Up front: Xcode 7.1.1, OS 10.11.2, iOS 9.0.2 (on physical device)

I'm writing a small app that communicates with my Raspberry Pi. I've got some working code that's written in Obj-C (for iOS 7) borrowed from a tutorial, and it all works fine for me in Obj-C (connects and behaves as expected with the Pi). The issue lies with rewriting it for Swift/iOS 9 (which is the goal).

The good bit:

func initNetworkCommunication() {
    var readStream: Unmanaged<CFReadStreamRef>?
    var writeStream: Unmanaged<CFWriteStreamRef>?

    CFStreamCreatePairWithSocketToHost(nil, "192.168.1.22", 777, &readStream, &writeStream)

    inputStream = readStream?.takeRetainedValue() as! NSInputStream
    outputStream = writeStream?.takeRetainedValue() as! NSOutputStream

    inputStream.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
    outputStream.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)

    inputStream.open()
    outputStream.open()
}

I believe the issue to lie in the above as this is the last method call in the stack, however the application crashes quietly with little information:

Crash Screen

Any help would be much appreciated!
Please feel free to ask for more information.

p.s. I understand the formatting on this site is rather "strict", anything I missed, overdid, etc, please let me know :)

1

There are 1 best solutions below

3
Knight Artorias On BEST ANSWER

I've solved it.

Firstly:

inputStream = readStream?.takeRetainedValue() as! NSInputStream
outputStream = writeStream?.takeRetainedValue() as! NSOutputStream

Should be:

inputStream = readStream!.takeRetainedValue()
outputStream = writeStream!.takeRetainedValue()

Secondly, I abstracted the connection out of the ViewController (where I had this method initially) to a new class called Connection.

Here's Connection:

import UIKit

class Connection: NSObject, NSStreamDelegate {
    var inputStream: NSInputStream!
    var outputStream: NSOutputStream!

    func connect() {
        var readStream:  Unmanaged<CFReadStream>?
        var writeStream: Unmanaged<CFWriteStream>?

        CFStreamCreatePairWithSocketToHost(nil, "192.168.1.22", 777, &readStream, &writeStream)

        self.inputStream = readStream!.takeRetainedValue()
        self.outputStream = writeStream!.takeRetainedValue()

        self.inputStream.delegate = self
        self.outputStream.delegate = self

        self.inputStream.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
        self.outputStream.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)

        self.inputStream.open()
        self.outputStream.open()
    }
}

Often I find starting to type these helps me out :p