2016-04-05 1 views
1

J'ai une classe singleton qui vérifie l'état de connexion de l'application.Objective-C: Obtenir le résultat d'une méthode de classe singleton après l'exécution de la méthode?

Il existe une méthode nommée attemptToLogin dans la classe singleton qui effectue une requête http avec des paramètres et renvoie des données json sur l'état de connexion. (Vrai ou faux)

maintenant dans la principale TabBarViewController je l'ai fait ce qui suit:

@interface CustomTabBarController() 

@end 

@implementation CustomTabBarController{ 
    LoginCheckSingleton *loginSingleton; 
    dispatch_queue_t myCustomQueue; 
} 
-(void)viewDidAppear:(BOOL)animated{ 
    myCustomQueue = dispatch_queue_create("com.myDomain.appName", NULL); 
    loginSingleton = [LoginCheckSingleton sharedInstance]; 
    dispatch_sync(myCustomQueue, ^{ 
     [loginSingleton attemptToLogin]; 
    }); 
    if([loginSingleton.loginstat isEqual: @"true"]){ 
     NSLog(@"Logged In"); 
    }else{ 
     NSLog(@"Not Logged In"); 
     [self performSegueWithIdentifier:@"goToLoginView" sender:self]; 
    } 
} 

Le dispatch_sync ne fonctionne pas correctement ici, je veux exécuter la fonction à l'intérieur du dispatch_sync et obtenir les résultats avant d'exécuter la if déclaration en dessous. Mais l'instruction if est exécutée avant la fin du bloc à l'intérieur de dispatch_sync.

C'est le Singleton Class:

#import "LoginCheckSingleton.h" 
#import "AFNetworking.h" 
#import "SSKeychain.h" 
#import "CustomTabBarController.h" 
static LoginCheckSingleton *sharedInstance = nil; 
@interface LoginCheckSingleton(){ 
    NSString *serverURLString; 
    NSURL *serverURL; 
    NSString *userId; 
    NSString *password; 
    NSString *email; 
    NSMutableArray *jsonContents; 
    NSMutableDictionary *dictionary; 
    NSString *loggedInStatus; 
    bool loggedInTF; 

} 

@end 
@implementation LoginCheckSingleton{ 
} 


+ (LoginCheckSingleton*) sharedInstance { 
    static dispatch_once_t _singletonPredicate; 
    static LoginCheckSingleton *_singleton = nil; 

    dispatch_once(&_singletonPredicate, ^{ 
     _singleton = [[super allocWithZone:nil] init]; 
    }); 

    return _singleton; 
} 

+ (id) allocWithZone:(NSZone *)zone { 
    return [self sharedInstance]; 
} 

-(void)attemptToLogin{ 
    // Retrieve credentials from Keychain 
    userId = [SSKeychain passwordForService:@"com.lazemni.iFresh" 
             account:@"ifreshUserId"]; 
    password = [SSKeychain passwordForService:@"com.lazemni.iFresh" 
             account:@"ifreshPassword"]; 
    email = [SSKeychain passwordForService:@"com.lazemni.iFresh" 
            account:@"ifreshEmail"]; 
    if(email == nil || password == nil){ 

     NSLog(@"empty username or password"); 
    }else{ 
     NSLog(@"not empty username or password"); 
     serverURLString = @"http://www.lazemni.com/demo/ifresh/api/login/"; 
     serverURLString = [serverURLString stringByAppendingString:email]; 
     serverURLString = [serverURLString stringByAppendingString:@"/"]; 
     serverURLString = [serverURLString stringByAppendingString:password]; 
     NSLog(@"%@",serverURLString); 
     serverURL = [NSURL URLWithString:serverURLString]; 

     NSURLRequest *request = [NSURLRequest requestWithURL:serverURL]; 
     //AFNetworking asynchronous url request 
     AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] 
              initWithRequest:request]; 

     operation.responseSerializer = [AFJSONResponseSerializer serializer]; 
     [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { 
      jsonContents = [responseObject objectForKey:@"login"]; 
      NSLog(@"%@",jsonContents); 
      dictionary = [jsonContents objectAtIndex:0]; 
      loggedInStatus = [dictionary objectForKey:@"status"]; 
      if([loggedInStatus isEqual: @"true"]){ 
       NSLog(@"Succefully loggedin!"); 
       [SSKeychain setPassword:[dictionary objectForKey:@"user_id"] forService:@"com.lazemni.iFresh" account:@"ifreshUserId"]; 
       [SSKeychain setPassword:[dictionary objectForKey:@"email"] forService:@"com.lazemni.iFresh" account:@"ifreshEmail"]; 
       [SSKeychain setPassword:[dictionary objectForKey:@"password"] forService:@"com.lazemni.iFresh" account:@"ifreshPassword"]; 
       self.loginstat = @"true"; 
       loggedInTF = true; 
      }else if([loggedInStatus isEqual: @"false"]){ 
       NSLog(@"Wrong email/password combination!"); 
       self.loginstat = @"false"; 
       loggedInTF = false; 
      } 
     } failure:nil]; 
     [operation start]; 
    } 
} 


@end 

Je ne ai jamais compris comment dispatch_sync fonctionne vraiment, Toute idée d'attendre le [loginSingleton attemptToLogin]; à la fin?

+0

Qu'est-ce attemptToLogin faire? Pourquoi doit-il être dans une fermeture d'expédition à tous? Pourquoi n'est pas exécuté en ligne? –

+0

J'ai ajouté la classe singleton avec la méthode appelée, vous pouvez la vérifier s'il vous plaît –

+0

Vous devez créer un callback pour la méthode 'attemptToLogin', après avoir vérifié la connexion terminée dans cette méthode, vous exécutez ce rappel. Et dans 'CustomTabBarController' déplacez l'instruction' if' vers ce bloc de rappel de la méthode 'tryToLogin' – Gintama

Répondre

1
- (void)attemptToLogin:(void(^)(BOOL login))complete { 
    ... 
    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { 
     .... 
     // After you get login status 
     complete(your_login_status_here); 
    } 
} 

Et CustomTabBarController

-(void)viewDidAppear:(BOOL)animated{ 
    myCustomQueue = dispatch_queue_create("com.myDomain.appName", NULL); 
    loginSingleton = [LoginCheckSingleton sharedInstance]; 

     [loginSingleton attemptToLogin:^(loginStatus){ 
       if([loginStatus isEqual: @"true"]){ 
        NSLog(@"Logged In"); 
       }else{ 
        NSLog(@"Not Logged In"); 
        dispatch_async(dispatch_get_main_queue(), { 
         [self performSegueWithIdentifier:@"goToLoginView" sender:self]; 
        }); 
       } 

     }]; 

} 
+0

Merci beaucoup! tu as sauvé ma journée :) –

2

attemptToLogin est probablement une méthode asynchrone. Vous voulez écrire tentToLogin de telle sorte qu'il vous donne un rappel lorsque la requête HTTP termine l'exécution. Vous pouvez le faire au moyen d'un bloc d'achèvement, d'un délégué ou d'une notification.

Si vous attendez la fin de la requête, vous finirez par bloquer le thread principal, ce qui gèlera les interactions de l'utilisateur et entraînera un affreux UX.

+0

J'ai ajouté la classe singleton, pouvez-vous jeter un coup d'oeil s'il vous plaît –