Question

The difference between NSInputStream * and CFReadStreamRef seems to be that the first one is an objective C object, while the second one is a native struct. Nevertheless, they are toll-free bridged.

I want to implement a program based on network streams.

  • [NSStream getStreamsToHost:port:inputStream:outputStream:] produces NSInputStream * and NSOutputStream *. However, on iOS, this method is not available.

    Therefore, CFStreamCreatePairWithSocketToHost has to be used on iOS.

    CFReadStreamRef readStream;
    CFWriteStreamRef writeStream;
    CFStreamCreatePairWithSocketToHost(
                     kCFAllocatorDefault, host, port, &readStream, &writeStream);
    NSInputStream *read = (__bridge NSInputStream *)readStream;
    NSOutputStream *write = (__bridge NSOutputStream *)writeStream;
    
  • When setting stream properties, not all properties are available when NSInputStream * is used. Especially the kCFStreamPropertyShouldCloseNativeSocket would be interesting to ensure that the socket is also closed when the corresponding stream is closed.

    Do I have to convert the NSInputStream * to a CFReadStreamRef to set this property, and then revert the conversion, to set such a property?

  • ...

The NSInputStream * seems to have multiple disadvantages. Is its only advantage really that I can provide an own subclass of it, while I cannot do so in the CFReadStreamRef case? When should which method be used?

Was it helpful?

Solution

In general, most Foundation/CoreFoundation toll-free bridged classes are also similar in terms of behavior. But you're right, this is not the case for NSInputStream * and CFReadStreamRef. Apple's Setting Up Socket Streams guide only explains what you describe. And even when using the latest initializers (like inputStreamWithURL: available in 10.6), it still doesn't work when url is remote (eg. http://...).

The main advantage I see to continue using NSInputStream is a better integration within an Objective-C application. At any time, you can try to change the property of your NSInputStream * object (read) like this:

if (!CFReadStreamSetProperty((CFReadStreamRef)read,
                              kCFStreamPropertyShouldCloseNativeSocket,
                              kCFBooleanTrue))
     failure("property change not accepted");

As an alternative to all of this, I would suggest to take a look at the NSURLRequest and NSURLConnection objects described in URL Loading System Programming Guide.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top