Функция обратного вызова CFReadStreamSetClient - Как дать функции обратного вызова C ссылку на содержащий класс? - PullRequest
1 голос
/ 14 марта 2011

Я предоставляю клиентскую функцию обратного вызова в потоке сетевого чтения ниже:

 -(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 не будет знать, что означает «я» в этом контексте.Может кто-нибудь дать мне указатель на то, как я могу обойти это?

Спасибо!

1 Ответ

2 голосов
/ 14 марта 2011

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];
}

(Поскольку это базовый базовый уровень, нет гарантии того, что пул авто-релиза существует, поэтому на всякий случай можно увидеть Objective-C в этих обратных вызовах, заключенных в пул авто-релиза.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...