I am assing a client callback function on a network read stream below:
-(void)connectToServer
{
if([self isServerConfigured])
{
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFHostRef host = CFHostCreateWithName(kCFAllocatorDefault, (CFStringRef)self.serverAddress);
CFStreamCreatePairWithSocketToCFHost(kCFAllocatorDefault, host, self.port, &readStream, &writeStream);
CFStreamClientContext myContext = {
0,
self,
(void *(*)(void *info))CFRetain,
(void (*)(void *info))CFRelease,
(CFStringRef (*)(void *info))CFCopyDescription
};
CFOptionFlags registeredEvents = kCFStreamEventHasBytesAvailable |
kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered;
if(CFReadStreamSetClient(readStream, registeredEvents, serverCB, &myContext))
{
CFReadStreamScheduleWithRunLoop(readStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
}
if(!CFReadStreamOpen(readStream)){
NSLog(@"Could not open read stream");
}
}
}
I would like this callback function to be able to call instance functions in the current object (self). It does not appear that CFReadStreamSetClient will allow me to change the callback functions signature and so I cannot just pass a reference to the current object to the callback I don't think.
This is the callback function:
void serverCB(CFReadStreamRef stream, CFStreamEventType event, void *myPtr)
{
switch(event) {
case kCFStreamEventHasBytesAvailable:
[self readStreamData:stream];
break;
开发者_Go百科 case kCFStreamEventErrorOccurred:
NSLog(@"A Read Stream Error Has Occurred!");
break;
case kCFStreamEventEndEncountered:
NSLog(@"A Read Stream Event End!");
break;
default:
break;
}
}
ServerCB will not know what 'self' is in this context. Can someone give me a pointer on how I can work around this?
Thanks!
myPtr
== self
in this case, as self
is the value you gave your context's info
field. That field is then passed to the callback by way of the last argument. So:
void serverCB(CFReadStreamRef stream, CFStreamEventType event, void *myPtr) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
{
MyClass *self = [[(MyClass *)myPtr retain] autorelease];
// ...
// ...
// ...
}
[pool drain];
}
(Because this is the Core Foundation level, there's no guarantee that an autorelease pool is in place, so it's common to see Objective-C in these callbacks wrapped in an autorelease pool, just in case.)
精彩评论