Как перенести асинхронный класс для создания этого синхронным? Использовать NSRunLoop?

Я в настоящее время работаю над приложением для iPhone, и у меня есть библиотека от третьего лица, которое имеет асинхронное поведение, но что я хотел бы перенестись со своим собственным классом и заставить его казаться синхронным.

Центральный класс в этой библиотеке, давайте назовем это классом Соединения, имеет несколько функций, которым разрешили их окончательный результат, когда методы на экземпляре класса делегата называют. То, что я пытаюсь сделать, является переносом этот класс и делегат так, чтобы это, казалось, было синхронно вместо асинхронного. Если бы я делал это в Java, то я использовал бы FutureTask или CountdownLatch или просто присоединился бы (). Но я не уверен лучший способ сделать это в Objective C.

Я запустил путем создания NSThread extenstion, NFCThread, который соответствует вышеупомянутому протоколу делегата. Идея состоит в том, что я был бы init и NFCThread, передать экземпляр NFCThread setDelegate методу Соединения, запустить поток и затем назвать асинхронный метод для Соединения. Мое ожидание состоит в том, что один из этих трех методов делегата для экземпляра NFCThread назвали бы, в конечном счете заставив поток выйти.

Для моделирования соединения, я сделал следующее. Я добавил NSConditionalLock к NFCThread:

joinLock = [[NSConditionLock alloc] initWithCondition:NO];

Код вокруг вызова к Соединению выглядит примерно так:

NFCThread *t = [[NFCThread alloc] init];
[connection setDelegate:t];
[t start];

[connection openSession];
// Process errors, etc...

[t.joinLock lockWhenCondition:YES];
[t.joinLock unlock];
[t release];
[connection setDelegate:nil];

Протокол для делегата имеет три метода. В NFCThread я реализовал каждый метод что-то вроде этого:

- (void)didReceiveMessage:(CommandType)cmdType 
                     data:(NSString *)responseData 
               length:(NSInteger)length {
    NSLog(@"didReceiveMessage");
    // Do something with data and cmdType...
    [joinLock lock];
    [joinLock unlockWithCondition:YES];
    callBackInvoked = YES;
}

Я перегружал основной метод NFCTHREAD так, чтобы это просто циклы постоянно. Что-то вроде этого:

while (!callBackInvoked) { ; }

Я нашел, что это не действительно хорошая идея начиная с него использование CPU причины для прохождения через крыши. Так вместо этого я пытался использовать цикл выполнения от некоторых примеров, которые я нашел на этом сайте:

NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];

while (!callBackInvoked) {
    [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}

В обеих из моих реализаций всегда блокируется основной поток, и кажется, что ни один из методов делегата никогда не называют. Однако я знаю, что библиотека функционирует правильно и что вызовы к методам делегата обычно называют.

Я чувствую, что пропускаю что-то очевидное здесь. Любая справка очень ценится.

Богатый

6
задан richever 5 August 2010 в 22:51
поделиться