Я в настоящее время работаю над приложением для 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]];
}
В обеих из моих реализаций всегда блокируется основной поток, и кажется, что ни один из методов делегата никогда не называют. Однако я знаю, что библиотека функционирует правильно и что вызовы к методам делегата обычно называют.
Я чувствую, что пропускаю что-то очевидное здесь. Любая справка очень ценится.
Богатый