NSNetService and Automatic Reference Counting (ARC)
Q:
I create a pair of streams using -[NSNetService getInputStream:outputStream:]
and, after converting my project to automatic reference counting (ARC), my streams refuse to open properly. What's causing this?
A: -[NSNetService getInputStream:outputStream:]
has a number of outstanding bugs
(r. 6868813)
(r. 9821932)
(r. 9856751)
, some of which are exacerbated by ARC. The best way to avoid all of these problems is to drop down a level and use CFStreamCreatePairWithSocketToNetService
to create your streams. The code in Listing 1 shows how you can create a category on NSNetService that provides a functional replacement for -[NSNetService getInputStream:outputStream:]
.
Listing 1 A functional replacement for -[NSNetService getInputStream:outputStream:]
@interface NSNetService (QNetworkAdditions) |
- (BOOL)qNetworkAdditions_getInputStream:(out NSInputStream **)inputStreamPtr |
outputStream:(out NSOutputStream **)outputStreamPtr; |
@end |
@implementation NSNetService (QNetworkAdditions) |
- (BOOL)qNetworkAdditions_getInputStream:(NSInputStream **)inputStreamPtr |
outputStream:(NSOutputStream **)outputStreamPtr |
{ |
BOOL result; |
CFReadStreamRef readStream; |
CFWriteStreamRef writeStream; |
result = NO; |
readStream = NULL; |
writeStream = NULL; |
if ( (inputStreamPtr != NULL) || (outputStreamPtr != NULL) ) { |
CFNetServiceRef netService; |
netService = CFNetServiceCreate( |
NULL, |
(__bridge CFStringRef) [self domain], |
(__bridge CFStringRef) [self type], |
(__bridge CFStringRef) [self name], |
0 |
); |
if (netService != NULL) { |
CFStreamCreatePairWithSocketToNetService( |
NULL, |
netService, |
((inputStreamPtr != NULL) ? &readStream : NULL), |
((outputStreamPtr != NULL) ? &writeStream : NULL) |
); |
CFRelease(netService); |
} |
// We have failed if the client requested an input stream and didn't |
// get one, or requested an output stream and didn't get one. We also |
// fail if the client requested neither the input nor the output |
// stream, but we don't get here in that case. |
result = ! ((( inputStreamPtr != NULL) && ( readStream == NULL)) || |
((outputStreamPtr != NULL) && (writeStream == NULL))); |
} |
if (inputStreamPtr != NULL) { |
*inputStreamPtr = CFBridgingRelease(readStream); |
} |
if (outputStreamPtr != NULL) { |
*outputStreamPtr = CFBridgingRelease(writeStream); |
} |
return result; |
} |
@end |
Document Revision History
Date | Notes |
---|---|
2011-10-28 | New document that describes an issue with NSNetService that can cause connections never to complete. |
Copyright © 2011 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2011-10-28