iphone-uialertview-thread

#iphone #uiactivityindicatorview

#iPhone #uiactivityindicatorview

Вопрос:

в iphone я вызываю один веб-сервис для проверки входа в систему…

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

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

но когда я включаю кнопку отмены, возникает ошибка, любой может помочь

Мой код

 -(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 Resu<

}
-(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:

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