我正在为下面的网络读取流提供客户端回调函数:
-(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");
}
}
}
我希望这个回调函数能够调用当前对象(self)中的实例函数。 CFReadStreamSetClient似乎不允许我更改回调函数签名,所以我不能只将当前对象的引用传递给我不认为的回调。
这是回调函数:
void serverCB(CFReadStreamRef stream, CFStreamEventType event, void *myPtr)
{
switch(event) {
case kCFStreamEventHasBytesAvailable:
[self readStreamData:stream];
break;
case kCFStreamEventErrorOccurred:
NSLog(@"A Read Stream Error Has Occurred!");
break;
case kCFStreamEventEndEncountered:
NSLog(@"A Read Stream Event End!");
break;
default:
break;
}
}
ServerCB不知道在这种情况下'self'是什么。有人能指点我如何解决这个问题吗?
谢谢!
答案 0 :(得分:2)
myPtr
== self
,因为self
是您为上下文的info
字段提供的值。然后通过最后一个参数将该字段传递给回调。所以:
void serverCB(CFReadStreamRef stream, CFStreamEventType event, void *myPtr) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
{
MyClass *self = [[(MyClass *)myPtr retain] autorelease];
// ...
// ...
// ...
}
[pool drain];
}
(因为这是Core Foundation级别,所以无法保证自动释放池已就绪,所以在自动释放池中包含这些回调中的Objective-C是很常见的,以防万一。)