我有一个单例类来检查应用程序的登录状态。
在单例类中有一个名为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 :(得分: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];
});
}
}];
}