Objective-C:在完成方法后获得单例类方法的结果?

时间:2016-04-05 01:12:29

标签: ios objective-c objective-c-blocks dispatch-async

我有一个单例类来检查应用程序的登录状态。

在单例类中有一个名为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];完成吗?

2 个答案:

答案 0 :(得分:2)

attemptToLogin可能是一种异步方法。您希望以这样的方式编写attemptToLogin,以便在HTTP请求完成执行时为您提供回调。您可以通过完成块,代理或通知来实现。

如果您等待请求完成,您将最终阻止主线程,这将冻结用户交互,导致可怕的用户体验。

答案 1 :(得分: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];
                    });
               }

        }];

}