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