CFReadStreamRef vs. NSInputStream *
-
09-06-2021 - |
题
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 *
andNSOutputStream *
. 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 thekCFStreamPropertyShouldCloseNativeSocket
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 aCFReadStreamRef
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?
解决方案
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.