准备工作:搭建服务器,后台写好逻辑代码
一、本人用Eclipse+apache搭建的服务器,后台只是写了简单的登录界面,如果密码和用户名都正确就返回登录成功,否则返回登录失败。
二、对url的分析
http://localhost:8080/MJServer/login?username=%@&pwd=%@
http为协议头
localhost:8080 为主机地址,localhost是本机地址,如果是网络的主机地址就填网络主机地址
MJServer/login为接口,后面是参数,在数据库中也是关键字段
三、NSRULSession的使用步骤
1.创建URL(必须)
NSURL *url = [NSURL URLWithString:urlString];
2.创建请求对象,设置请求对象(不是必须)
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//设置请求对象的超时时间为4s
request.timeoutInterval = 4;
3.创建NSURLSessionConfiguration,并且设置(不是必须)
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
//超时时间
config.timeoutIntervalForRequest = 5;
4.创建NSURLSession(必须)
NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
5.创建任务(必须)
//这种方法可以处理文件操作等大型数据
NSURLSessionDataTask *task = [session dataTaskWithRequest:request];
//这种方法处理一些轻量数据
// NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
}
6.启动任务(必须)
[task resume];
四、NSURLSession中使用Get方式请求
默认就是Get方式。
/**Get方式*/
-(void)loginOnClickByGetMethod
{
NSString *username = self.textFieldOne.text;
NSString *password = self.textFieldTwo.text;
if (username.length == 0 || password.length == 0) {
[MBProgressHUD showError:@"请输入账号或密码"];
return;
}
NSString *urlString = [NSString stringWithFormat:@"http://localhost:8080/MJServer/login?username=%@&pwd=%@",username,password];
//对url进行转码(url不允许有中文)
urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSURL *url = [NSURL URLWithString:urlString];
[MBProgressHUD showMessage:@"拼命加载中"];
//创建请求对象
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//设置请求对象的超时时间为4s
request.timeoutInterval = 4;
[self setupURLSession:request];
}
-(void)setupURLSession:(NSURLRequest *)request
{
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
//超时时间
config.timeoutIntervalForRequest = 5;
//创建session
NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
//这种方法处理一些轻量数据
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//隐藏HUD(刷新UI界面,一定要放在主现场,不能放在子线程)
[MBProgressHUD hideHUD];
if(data)//data有值才返回JSON数据,否则JSON为nil程序会崩
//请求成功
{
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
NSLog(@"dict = %@",dict);
NSString *error = dict[@"error"];
if (error) {
[MBProgressHUD showError:error];
}
else
{
NSString *success = dict[@"success"];
[MBProgressHUD showSuccess:success];
}
}
else//请求失败
{
[MBProgressHUD showError:@"网络繁忙,请稍后再试"];
}
}];
//启动任务
[task resume];
}
五、NSURLSession中使用Post方式请求
/**Post方式*/
-(void)loginOnClickByPostMethod
{
NSString *username = self.textFieldOne.text;
NSString *password = self.textFieldTwo.text;
if (username.length == 0 || password.length == 0) {
[MBProgressHUD showError:@"请输入账号或密码"];
return;
}
NSURL *url = [NSURL URLWithString:@"http://localhost:8080/MJServer/login"];
[MBProgressHUD showMessage:@"拼命加载中"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.timeoutInterval = 4;
request.HTTPMethod = @"POST";
//设置请求头告诉服务器客户端的类型
// [request setValue:@"android-ios" forHTTPHeaderField:@"User-Agent"];
//设置请求体
NSString *param = [NSString stringWithFormat:@"username=%@pwd=%@",username,password];
//转码
request.HTTPBody = [param dataUsingEncoding:NSUTF8StringEncoding];
[self setupURLSession:request];
}
-(void)setupURLSession:(NSURLRequest *)request
{
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
//超时时间
config.timeoutIntervalForRequest = 5;
//创建session
NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
//这种方法可以处理文件操作等大型数据
NSURLSessionDataTask *task = [session dataTaskWithRequest:request];
//启动任务
[task resume];
}
因为NSURLSessionDataTask用的是以上的方式,不是block的方式,所以要配合NSURLSessionDataDelegate一起用。首先要遵守NSURLSessionDataDelegate协议,然后就是写上代理方法。
#pragma mark - NSURLSessionDataDelegate
//接收到服务器相应的时候调用该方法
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
{
//注意:需要使用completionHandler回调告诉系统应该如何处理服务器返回的数据
//默认是取消的
/*
NSURLSessionResponseCancel = 0, 默认的处理方式,取消
NSURLSessionResponseAllow = 1, 接收服务器返回的数据
NSURLSessionResponseBecomeDownload = 2,变成一个下载请求
NSURLSessionResponseBecomeStream 变成一个流
*/
NSLog(@"didReceiveResponse----%@--%@",[NSThread currentThread],dataTask);
completionHandler(NSURLSessionResponseAllow);
}
//接收到服务器返回的数据就会调用该方法,如果数据较大的话该方法可能会调用多次
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
NSLog(@"didReceiveData----%@",[NSThread currentThread]);
[self.responsedata appendData:data];
NSLog(@"self.responsedata = %@",[NSJSONSerialization JSONObjectWithData:self.responsedata options:NSJSONReadingMutableLeaves error:nil]);
}
//当请求完成时候调用该方法,如果请求失败,则有error值
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
NSLog(@"didCompleteWithError----%@",[NSThread currentThread]);
[MBProgressHUD hideHUD];
//请求成功
{
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:self.responsedata options:NSJSONReadingMutableLeaves error:nil];
NSLog(@"dict = %@",dict);
NSString *error = dict[@"error"];
if (error) {
[MBProgressHUD showError:error];
}
else
{
NSString *success = dict[@"success"];
[MBProgressHUD showSuccess:success];
}
}
}
六、由于服务器返回的是JSON格式的数据,由于编码原因,中文会打印乱码。此时,我们用一个创建一个分类,继承NSDictionary的分类,实现方法如下:
@implementation NSDictionary (JsonLog)
-(NSString *)descriptionWithLocale:(id)locale indent:(NSUInteger)level
{
//初始化可变字符串
NSMutableString *string = [NSMutableString string];
//拼接开头[
[string appendString:@"["];
//拼接字典中所有的键值对
[self enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
[string appendFormat:@"%@:",key];
[string appendFormat:@"%@",obj];
}];
//拼接结尾]
[string appendString:@"]"];
return string;
}
@end
这样就能直接打印出来中文,方便数据的测试。
测试数据:
2017-04-26 17:40:17.738 NSURLSession[3068:286241] didReceiveResponse----<NSThread: 0x600000077d40>{number = 1, name = main}--<__NSCFLocalDataTask: 0x7f88a5431320>{ taskIdentifier: 1 } { suspended }
2017-04-26 17:40:17.738 NSURLSession[3068:286241] didReceiveData----<NSThread: 0x600000077d40>{number = 1, name = main}
2017-04-26 17:40:17.739 NSURLSession[3068:286241] self.responsedata = [success:登录成功]
2017-04-26 17:40:17.739 NSURLSession[3068:286241] didCompleteWithError----<NSThread: 0x600000077d40>{number = 1, name = main}
2017-04-26 17:40:17.739 NSURLSession[3068:286241] dict = [success:登录成功]