2015-11-03 2 views
1

Я разрабатываю приложение со страницей входа. Когда приложение запускается, отображается экран входа в систему, и вы не можете получить доступ к приложению до тех пор, пока не будете подключены. Чтобы подключиться к приложению, вы вводите свое имя пользователя и пароль. Когда вы нажимаете кнопку «connect», json-данные, содержащие имя пользователя и пароль, отправляются в веб-службу, которые проверяют наличие учетных данных. Если они существуют, сервер отправляет json-файл, содержащий «существует»: «true»обработчик входа и завершения

Проблема в том, что код, проверяющий этот Json-файл, находится в завершенииHandler моего NSURLSession, а метод возвращает «NO» перед данными Json , поэтому я не могу подключиться к моему приложению. Как это трудно объяснить, вот мой код:

GSBconnexion.m:

#import "GSBconnexion.h" 

@implementation GSBconnexion 





-(bool)logConnexionWithUserName:(NSString *)username 
        password:(NSString *)password{ 


    __block BOOL allowConnexion; 
    NSDictionary *connexion = @{ 
           @"username": username, 
           @"password": password, 
           @"target": @"app" 
           }; 


    NSError *error; 
    NSData *jsonLogData = [NSJSONSerialization dataWithJSONObject:connexion             options:NSJSONWritingPrettyPrinted 
                error:&error]; 


if (! jsonLogData) { 
    NSLog(@"Got an error: %@", error); 
} 



NSData *logData = jsonLogData; 
NSString *testString = [[NSString alloc] initWithData:logData encoding:NSUTF8StringEncoding]; 
NSString *logLength = [NSString stringWithFormat:@"%lu", (unsigned long)[testString length]]; 
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; 
[request setURL:[NSURL URLWithString:@"http://192.168.5.133:1337/login"]]; 
[request setHTTPMethod:@"POST"]; 
[request setValue:logLength forHTTPHeaderField:@"Content-lenght"]; 
[request setValue:@"application/json" forHTTPHeaderField:@"Accept"]; 
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; 
[request setHTTPBody:logData]; 
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; 
[[session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){ 
    NSDictionary *serverResponse = [NSJSONSerialization JSONObjectWithData:data options: 
            NSJSONReadingMutableContainers error:&error]; 

    int canIConnect = [serverResponse[@"exist"] intValue]; 

    NSLog(@"%d",canIConnect); 




if (canIConnect == 1) { 
     NSLog(@"OKKK"); 
     allowConnexion = YES; 
     NSString *sessionID = [[NSString alloc]initWithString:serverResponse[@"_id"]]; 
     NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; 
     [userDefaults setObject:sessionID forKey:@"SessionID"]; 
     [userDefaults synchronize]; 

      NSLog(@"ID Session:%@",[userDefaults objectForKey:@"sessionID"]); 
    } 

    else { 

     allowConnexion=NO; 
    } 

}] resume]; 

NSLog(@"JSON envoyé: \n\n%@",testString); 

return allowConnexion; 
} 



@end 

GSBLoginController:

- (IBAction)connect:(id)sender { 

    connectButton.hidden = YES; 
    loading.hidden = NO; 

    UIViewController* homePage = [self.storyboard instantiateViewControllerWithIdentifier:@"homePage"]; 

    GSBconnexion *login = [[GSBconnexion alloc]init]; 

    NSString *username = [[NSString alloc]initWithFormat:@"%@",usernameTextField.text]; 
    NSString *password = [[NSString alloc]initWithFormat:@"%@",pwdTextField.text]; 

    BOOL authorized = [login logConnexionWithUserName:username password:password]; 
    if (authorized) { 
     [self presentViewController:homePage animated:YES completion:nil]; 
    } 

    else { 
     connectButton.hidden = NO; 
     loading.hidden=YES; 
     [email protected]""; 
     [email protected]""; 
     errorLabel.text = @"Connexion impossible, merci de réessayer.\nSi le problème persiste, veuillez contacter un administrateur."; 
    } 

    NSLog(authorized ? @"Yes" : @"No"); 
} 

Я надеюсь, что вы меня поняли, спасибо за вашу помощь!

Simon

ответ

1

Проблема заключается в том, что вы ожидаете, возвращаемое значение из метода, которая выполняется асинхронно. Таким образом, в основном return allowConnexion происходит сразу, хотя dataTask все еще продолжается в фоновом режиме. Таким образом, вы полагаетесь на неправильное значение. В основном, что вы хотите сделать, это скопировать то, что происходит в dataTask с обработчиком завершения.

Таким образом, вы могли бы сказать что-то вроде typedef void (^CompletionBlock) (BOOL isFinished);

Затем измените метод входа, чтобы включить блок завершения в качестве последнего аргумента и не возвращает ничего:

-(void)logConnexionWithUserName:(NSString *)username 
        password:(NSString *)password 
        withCompletion:(CompletionBlock)completionBlock 

Тогда внутри completionHandler в dataTask вызовет completionBlock прохождения в значении allowConnexion.

Наконец, после того, как вы сделали все это в своем контроллере входа в систему, вы реализуете этот новый метод, а внутри блока завершения вы можете соответствующим образом обновить свой вид. Его будет выглядеть примерно так:

- (void)thingWithCompletion:(CompletionBlock)completionBlock 
{ 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     completionBlock(YES); 
    }); 
} 

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    [self thingWithCompletion:^(BOOL isFinished) { 
     //update UI 
    }]; 
} 

Помните, что так как вы на фоне поток и собираетесь обновить пользовательский интерфейс по завершению вы будете хотеть, чтобы направить в основную очередь, а также. Вот почему вызов completionBlock(YES); завернут в вызов dispatch_async.

Смежные вопросы