iphone-UIAlertView-thred - PullRequest
0 голосов
/ 12 мая 2011

в iphone, я вызываю один веб-сервис для проверки логина ...

Когда приложение не обрабатывается, я показываю UIAlertview С UIActivityIndicatorView используя нить ,,

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

но когда я включаю кнопку отмены, то происходит ОШИБКА, Любой может помочь

Мой код

-(NSMutableString*) getLoginMessage:(NSString*) UserName : (NSString *) Password
{

    [NSThread detachNewThreadSelector:@selector(showAlertMethod) toTarget:self withObject:nil];

    NSArray *Keys =[[NSArray alloc] initWithObjects:@"LoginName",@"PassWord",nil];
    NSArray *KeyValue =[[NSArray alloc] initWithObjects:UserName,Password,nil];

    operationName=[[NSString alloc] init];
    operationName =@"ClientLogin";
    NSString *StrService=[[NSUserDefaults standardUserDefaults] objectForKey:@"WebService"];
    NSURL *WebServiceUrl=[WebServiceHelper generateWebServiceHTTPGetURL:StrService : operationName : Keys :KeyValue];
    NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:WebServiceUrl];

    [parser setShouldReportNamespacePrefixes:NO];
    [parser setShouldResolveExternalEntities:NO];
    [parser setDelegate:self];
    [parser parse];

    [Keys release];
    [KeyValue release];
    [StrService release];
    [WebServiceUrl release];
    //[parser release];
    [NSThread detachNewThreadSelector:@selector(dismissAlertMethod) toTarget:self withObject:nil];

    return Result;

}
-(void)showAlertMethod
{
    NSAutoreleasePool *pool1=[[NSAutoreleasePool alloc]init];           
    progressAlert = [[UIAlertView alloc] initWithTitle:@"Loging in...\nPlease wait...\n" message:@"" delegate:nil cancelButtonTitle:nil otherButtonTitles:nil];

    CGRect alertFrame = progressAlert.frame;
    UIActivityIndicatorView* activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
    activityIndicator.frame = CGRectMake(135,alertFrame.size.height+75, alertFrame.size.width,30);
    activityIndicator.hidden = NO;
    activityIndicator.contentMode = UIViewContentModeCenter;
    [activityIndicator startAnimating]; 
    [progressAlert addSubview:activityIndicator];
    [activityIndicator release];
    [progressAlert show];

    [pool1 release];    
}
-(void)dismissAlertMethod
{
    NSAutoreleasePool *pool2=[[NSAutoreleasePool alloc]init];
    [progressAlert dismissWithClickedButtonIndex:0 animated:YES];
    [pool2 release];
}

1 Ответ

0 голосов
/ 12 мая 2011

Есть некоторые серьезные недостатки в том, как вы решаете проблему.Во-первых, вы не должны отсоединять новые потоки, чтобы показать и скрыть представление предупреждений, все классы 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], если пользователь отменяет или отклоняет предупреждение, когда делегат получает обратный вызов.

...