Search code examples
iosswiftnsstream

NSStream on iphone not working


  func connect(host: String, port: Int)
{

    self.host = host
    self.port = port

    NSStream.getStreamsToHostWithName(host, port: port, inputStream: &inputStream, outputStream: &outputStream)

    if inputStream != nil && outputStream != nil
    {
        // Set delegate
        inputStream!.delegate = self
        outputStream!.delegate = self

        // Schedule
        inputStream!.scheduleInRunLoop(.mainRunLoop(), forMode: NSDefaultRunLoopMode)
        outputStream!.scheduleInRunLoop(.mainRunLoop(), forMode: NSDefaultRunLoopMode)

        // Open!
        inputStream!.open()
        outputStream!.open()
    }
}

When I start above code in the XCode Simulator it works, but it gives me the following error when I start it on my iPhone:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[NSStream getStreamsToHostWithName:port:inputStream:outputStream:]: unrecognized selector sent to class 0x3b81786c'


Solution

  • getStreamsToHostWithName(_:port:inputStream:outputStream:) in NSStream is not avaialable in iOS 7. It's introduced in iOS 8.

    extension NSStream {
    
        @availability(iOS, introduced=8.0)
        class func getStreamsToHostWithName(hostname: String, port: Int, inputStream: AutoreleasingUnsafeMutablePointer<NSInputStream?>, outputStream: AutoreleasingUnsafeMutablePointer<NSOutputStream?>)
    }
    

    You have to use CFStreamCreatePairWithSocketToHost instead:

    class Connection: NSObject, NSStreamDelegate {
    
        var inputStream:NSInputStream?
        var outputStream:NSOutputStream?
    
        func connect(host: String, port: Int) {
    
            var inStreamUnmanaged:Unmanaged<CFReadStream>?
            var outStreamUnmanaged:Unmanaged<CFWriteStream>?
            CFStreamCreatePairWithSocketToHost(nil, host, UInt32(port), &inStreamUnmanaged, &outStreamUnmanaged)
            inputStream = inStreamUnmanaged?.takeRetainedValue()
            outputStream = outStreamUnmanaged?.takeRetainedValue()
    
            if inputStream != nil && outputStream != nil {
                // Set delegate
                inputStream!.delegate = self
                outputStream!.delegate = self
    
                // Schedule
                inputStream!.scheduleInRunLoop(.mainRunLoop(), forMode: NSDefaultRunLoopMode)
                outputStream!.scheduleInRunLoop(.mainRunLoop(), forMode: NSDefaultRunLoopMode)
    
                // Open!
                inputStream!.open()
                outputStream!.open()
            }
        }