2016-04-05 5 views
1

У меня есть одноэлементный класс, который проверяет статус входа в приложение.Objective-C: Получите результат метода singleton-class после завершения выполнения метода?

В методе Singleton есть метод с именем attemptToLogin, который делает HTTP-запрос с параметрами и возвращает данные json о состоянии входа. (Истина или ложь)

Теперь в главном TabBarViewController я сделал следующее:

@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]; 
    } 
} 

dispatch_sync не работает должным образом здесь, я хочу, чтобы выполнить функцию внутри dispatch_sync и получить результаты перед выполнением if заявление под ним. Но оператор if выполняется до завершения блока внутри dispatch_sync.

Это 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 

Я никогда не понимал, как dispatch_sync действительно работает, Любая идея, как ждать [loginSingleton attemptToLogin]; закончить?

+0

Что attemptToLogin делать? Почему он вообще должен быть в закрытии отправки? Почему не выполняется inline? –

+0

Я добавил класс singleton с вызванным методом, вы можете его проверить –

+0

Вам нужно создать обратный вызов для метода 'tryToLogin', после проверки завершения входа в этот метод вы выполните этот обратный вызов. И в 'CustomTabBarController' переместите оператор' if' в этот блок обратного вызова метода 'tryToLogin' – Gintama

ответ

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

И 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

Спасибо вам большое! ты спас мой день :) –

2

attemptToLogin, вероятно, является асинхронным методом. Вы хотите написать tryToLogin таким образом, чтобы он вызывал обратный вызов, когда HTTP-запрос завершает выполнение. Вы можете сделать это с помощью блока завершения или делегата или уведомления.

Если вы дождались окончания запроса, вы в конечном итоге заблокируете основной поток, который заморозит взаимодействие пользователя, что приведет к ужасному UX.

+0

Я добавил класс singleton, можете ли вы взглянуть на него, пожалуйста, –