先解释一下下面代码的做用:后端
整个方法是判断是否登录成功并返回判断结果。网络
使用JSON格式的数据发送帐号密码到后端,并获得一个JSON,里面包括登录是否成功的信息,LoginState为0成功,其余为失败session
其中NSURLSessionDataTask是异步执行的app
疑问在注释中异步
-(NSInteger)postLoginJson:(NSString *)url withStuid:(NSString *)stuid withPwd:(NSString *)pwd{函数
NSDictionary *dic = @{@"stuid":stuid,@"pwd":pwd};post
NSData *data = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:nil];ui
NSURL *URL = [NSURL URLWithString:url];url
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];spa
[request setHTTPMethod:@"POST"];
[request setValue:@"application/jason" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:data];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data,NSURLResponse *response,NSError *error){
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
//其中 setBool 有bug
NSLog(@"loginState:%@",dic[@"loginState"]); //这是一个输出,返回状态值。
if([dic[@"loginState"] integerValue] == 0){
[userDefaults setInteger:0 forKey:@"tempBool"];
[userDefaults synchronize];
}
else{
[userDefaults setInteger:1 forKey:@"tempBool"];
[userDefaults synchronize];
}
}];
[task resume];
while ([task state] != NSURLSessionTaskStateCompleted) {
NSLog(@"state %ld",(long)[task state]);//这也是一个输出,当未完成时,一直输出。
} //此段代码是为了让任务完成后再往下执行,但不管如何,都是先输出willReturn而不是loginState
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSInteger willReturn = [userDefaults integerForKey:@"tempBool"];
NSLog(@"willReturn %ld",(long)willReturn);//这是函数返回值
[userDefaults removeObjectForKey:@"tempBool"];
[userDefaults synchronize];
//NSLog(willReturn);
return willReturn;
}
最终输出的结果就是:
先是一堆 while中的state
而后willReturn
而后loginState
按道理不是应该先loginState先输出吗?
3月21日更新
虽然加入了while等待任务完成,但这个任务指的是数据下载任务,也就是当收到登录状态返回值以后,此任务就为completed状态了,可是complationHandler中的指令这时才开始执行,而且是异步的,因此此while没用,最后的解决办法是把这个函数放在了LoginViewContorller,直接在complationHandler中执行相关UI更新。
目前找不到断定complationHandler运行状态的方法。
3月22日更新
从NSURLSessionDataTaskDelegate下手完全解决了这个问题。仍能够封装网络访问为一个model,为NSURLSessionDataTask传入代理指针,LoginViewController实现代理便可。
代码
VisitWeb.m
-(void)getJson:(NSString *)url withCurrentController:(id)delegate{
NSURLSessionConfiguration* ephConfiguration=[NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession* session=[NSURLSession sessionWithConfiguration:ephConfiguration delegate:delegate delegateQueue:[NSOperationQueue mainQueue]];
NSURL* URL=[NSURL URLWithString:url];
NSURLSessionDataTask* dataTask=[session dataTaskWithURL:URL];
[dataTask resume];
}
在相应文件里新建实例并设置代理便可。
VisitToGetJson *vj = [[VisitToGetJson alloc]init];
[vj getJson:@"http://120.27.120.48/stucard" withCurrentController:self];