Есть некоторые серьезные недостатки в том, как вы решаете проблему.Во-первых, вы не должны отсоединять новые потоки, чтобы показать и скрыть представление предупреждений, все классы UIKit должны вызываться из основного потока (существует только несколько документированных исключений) .
То, что вы хотите, это API, разработанный для асинхронной отправки запроса на вход.Я бы посоветовал вам использовать шаблон Sync-Async для этого.Я написал более длинную запись в блоге на эту тему здесь: http://blog.jayway.com/2011/04/28/sync-asyn-pair-pattern-easy-concurrency-on-ios/
По сути, я считаю, что вам нужны два открытых метода:
-(NSString*)loginMessageWithName:(NSString*)name
password:(NSString*)password
error:(NSError**)error;
-(NSOperation*)loginMessageWithName:(NSString*)name
password:(NSString*)password
delegate:(id<LoginMessageDelegate>)delegate;
Первый метод является синхронным, реализуйте его как простойкак вам угодно, никаких потоков ни на одной вещи, просто заставьте ее работать.
Второй метод - это обертка, которая создает экземпляры NSOperation
объектов и помещает их в некоторую очередь.Возврат операции позволяет отменить ее, но результат будет возвращен делегату.Вероятно, делегату нужно будет выглядеть примерно так:
@protocol LogonMessageDelegate <NSObject>
-(void)didReceiveLoginMessage:(NSString*)message;
-(void)failedLoginMessageWithError:(NSError*)error;
@end
Реализация loginMessageWithName:password:delegate:
очень проста:
NSOperation* op = [[LoginMessageOperation alloc] initWithName:name
password:password
delegate:delegate];
[myOperationQueue addOperation:op];
return [op autorelease];
Большая часть работы будет выполнена в вашем NSOperation
метод подкласса main
.Здесь вы вызываете синхронную реализацию, проверяете отмену и при необходимости перезваниваете делегату.Вероятно, что-то вроде этого:
-(void)main {
NSError* error = nil;
NSString* message = [logonMessageManager logonWithName:name
password:password:
error:&error];
if (![self isCancelled]) {
if (message) {
[delegate performSelectorOnMainThread:@selector(didReceiveLoginMessage:)
withObject:message
waitUntilDone:NO];
} else {
[delegate performSelectorOnMainThread:@selector(didReceiveLoginMessage:)
withObject:error
waitUntilDone:NO];
}
}
}
Затем настройте и обработайте представление предупреждений в главном потоке.Вызовите [operation cancel]
, если пользователь отменяет или отклоняет предупреждение, когда делегат получает обратный вызов.