Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Toll-free bridging and pointer access in Swift

Tags:

I am porting an App from Objective-C to Swift and I need to use the following method:

CFStreamCreatePairWithSocketToHost(alloc: CFAllocator!, host: CFString!, port: UInt32, \ readStream: CMutablePointer<Unmanaged<CFReadStream>?>, \ writeStream: CMutablePointer<Unmanaged<CFWriteStream>?>) 

The old logic looks like this (which several web sites seem to agree on):

CFReadStreamRef readStream = NULL; CFWriteStreamRef writeStream = NULL; CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)(host), port, \                                    &readStream, &writeStream);  NSInputStream inputStream = (__bridge_transfer NSInputStream *)readStream; NSOutputStream outputStream = (__bridge_transfer NSOutputStream *)writeStream; 

Which works fine thanks to toll-free bridging. However, ARC does not exist in "Swift-space", and the type system has changed.

How do I turn my streams into instances of

CMutablePointer<Unmanaged<CFReadStream>?>, and CMutablePointer<Unmanaged<CFWriteStream>?> 

And then convert them back into NSStream subclasses after the CFStreamCreatePairWithSocketToHost call?

like image 244
Ephemera Avatar asked Jun 04 '14 04:06

Ephemera


1 Answers

I got it to work, here's my code: Make sure you keep a reference of the connection class somewhere :-)

class Connection : NSObject, NSStreamDelegate {     let serverAddress: CFString = "127.0.0.1"     let serverPort: UInt32 = 8443      private var inputStream: NSInputStream!     private var outputStream: NSOutputStream!      func connect() {         println("connecting...")          var readStream:  Unmanaged<CFReadStream>?         var writeStream: Unmanaged<CFWriteStream>?          CFStreamCreatePairWithSocketToHost(nil, self.serverAddress, self.serverPort, &readStream, &writeStream)          // Documentation suggests readStream and writeStream can be assumed to         // be non-nil. If you believe otherwise, you can test if either is nil         // and implement whatever error-handling you wish.          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()     }      func stream(stream: NSStream, handleEvent eventCode: NSStreamEvent) {         println("stream event")     } } 
like image 78
Vincenzo Avatar answered Nov 03 '22 11:11

Vincenzo