Objective-C: 单例-class方法执行完后得到结果?

Objective-C: Get a result of a singleton-class method after finish executing the method?

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

单例 class 中有一个名为 attemptToLogin 的方法,它使用参数和 returns 使用 json 登录状态数据发出 http 请求。 (对或错)

现在主要 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]; 完成吗?

attemptToLogin大概是异步方法吧。您希望以这样的方式编写 attemptToLogin,以便在 HTTP 请求完成执行时为您提供回调。您可以通过完成块、委托或通知来做到这一点。

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

- (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];
                    });
               }

        }];

}