get和post
前言
get和post是我们实现API接口功能所需要的两种方式,实际上需要哪种根据网站对此的要求,而我们获取到所要的消息前,根据进程继续执行与否,我们又分为同步和异步两种方式。因此,我们实际上一共要学习同步get、同步post、异步get、异步post四种方式。
API接口
例子:
我们首先要为自己的软件找一个合适的API接口,这里我就以新浪接口为例子:
注册成功后,我们随便先注册一个企业级测试应用,然后我们就有了对应的access_token值,这个值是所有新浪微博的API接口都必要的一个值。
(图片之后补上)
然后我们点击文档-API文档,找到我们需要实现的功能对应的API接口,如果我们有不懂的可以找到API测试工具去把我们要的接口选中,它会给出返回的数据的形式和例子
(图片之后补上)
我们以其中公共微博为例,我们可以找到获取公共微博的API接口为statuses/public_timeline:
对于get方式而言:
我们需要接口的最终URL地址为:
接口的json的URL地址+?+我们这个接口需要的参数&参数….
(必要的写上,可选的根据需要写,参数之间用&符号连接)
https://api.weibo.com/2/statuses/public_timeline.json + ? +access_token=|这里写我们获取到的API接口的access_token|+?+|需要的其他可选参数|
这里我们举例子所以只需要用到必要的access_token参数,代码如下:
NSString *urlString = @"https://api.weibo.com/2/statuses/public_timeline.json?access_token=|这里写我们获取到的API接口的access_token|";
同步get
获取正确的服务器URL地址
我们首先要把需要的API接口文件的最终URL用字符串接收,如果此URL含有特殊字符或中文,我们就要对此进行编码(最好进行此步骤),编码后将其转为NSURL类型。
- (IBAction)synchronizationGet:(UIButton *)sender {
NSLog(@"同步get");
NSString *urlString = @"https://api.weibo.com/2/statuses/public_timeline.json?access_token=|这里写我们获取到的API接口的access_token|";
//编码
urlString =[urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSURL *url=[NSURL URLWithString:urlString];
服务器连接
然后我们用NSURLConnection类型提供的方法,如果同步就用sendSynchronousRequest方法,异步就用sendAsynchronousRequest方法与服务器进行连接。然后我们根据此方法需要的参数,去建立NSURLRequest、NSURLResponse、NSError三种类型的数据。我们除此之外还可以用NSURLConnectionDataDelegate协议代理的方法去进行服务器连接。
//创建一个url请求
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60];
NSURLResponse *httpURLResponse;
NSError *error;
//NSURLConnection类,和服务器连接
NSData *data=[NSURLConnection sendSynchronousRequest:request returningResponse:&httpURLResponse error:&error];
JSON数据格式解析
直接解析
//JSON数据格式解析,利用系统提供的API进行JSON数据解析
NSDictionary *dictionary=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
NSLog(@"dictionary = %@",dictionary);
NSDictionary *dic=[dictionary[@"statuses"] objectAtIndex: 0];
NSString *text=dic[@"text"];
}
用相应类解析
或者,我们可以用一个类去解析我们得到的JSON数据,这样子我们可以拆掉我们不要的外层数据,在大数据中,这样可以减轻我们解析的负担
//JSON数据格式解析,利用系统提供的API进行JSON数据解析
NSDictionary *dictionary=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
WeiboMode *mode1=[[WeiboMode alloc ]initWithDictionary:dictionary];
NSString *text=[mode1.statuses[0] objectForKey:@"text"];
NSLog(@"%@",text);
self.textView.text=text;
}
建一个解析json数据的类
由于我们获取到新浪微博返回的数据比较繁杂,而且我们每次得到的数据里面的外层结构都是一样的,我们可以建一个相关的类去解析数据
.h文件里面:
在声明文件中,我们首先如果要解析每一层数据,就要把此层的数据全部作为属性列出来,不然会报错。
#import <Foundation/Foundation.h>
@interface WeiboMode : NSObject
@property (nonatomic,strong)NSArray *statuses;
@property (nonatomic,strong)NSNumber *hasvisible;
@property (nonatomic,strong)NSNumber *previous_cursor;
@property (nonatomic,strong)NSNumber *next_cursor;
@property (nonatomic,strong)NSNumber *total_number;
@property (nonatomic,strong)NSNumber *interval;
-(id)initWithDictionary:(NSDictionary *)dictionary;
@end
.m文件:
#import "WeiboMode.h"
@implementation WeiboMode
-(id)initWithDictionary:(NSDictionary *)dictionary{
if (self=[super init]) {
[self setValuesForKeysWithDictionary:dictionary];
}
return self;
}
@end
异步get
获取正确的服务器URL地址
- (IBAction)AynchronizationGet:(UIButton *)sender {
NSString *urlString = @"https://api.weibo.com/2/statuses/public_timeline.json?access_token=|这里写我们获取到的API接口的access_token|";
//编码
urlString =[urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSURL *url=[NSURL URLWithString:urlString];
//创建一个url请求
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60];
服务器连接
服务器连接有两种方法,我们可以用协议代理的方法或直接请求的方法
用代理的方法服务器连接
(如果将异步的get和post两个方法写到同一个代理中,我们将此定义为全局变量,后面会提到)
NSURLConnection &connectionGet= [NSURLConnection connectionWithRequest:request delegate:self];
实现NSURLConnectionDataDelegate协议代理的必要的一些方法(接受完数据后,在connectionDidFinishLoading方法中解析JSON数据)
(为了接受数据,定义一个全局变量_mDataGet)
@interface ViewController ()<NSURLConnectionDataDelegate>
{
NSMutableData *_mDataGet;
}
@end
服务器开始响应,准备向客户发送数据
-(void)connection:(NSURLConnection *)connection
didReceiveResponse:(NSURLResponse *)response{
NSLog(@"服务器开始响应,准备向客户发送数据");
_mDataGet=[NSMutableData data];
从服务器接收到数据,并且此方法会执行多次
-(void)connection:(NSURLConnection *)connection
didReceiveData:(NSData *)data{
NSLog(@"从服务器接收到数据,并且此方法会执行多次");
[_mDataGet appendData:data];
}
服务器接收数据完成
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{
NSLog(@"服务器接收数据完成");
NSDictionary *dictionary=[NSJSONSerialization JSONObjectWithData:_mDataGet options:NSJSONReadingAllowFragments error:nil];
WeiboMode *model=[[WeiboMode alloc]initWithDictionary:dictionary];
NSString *text=[model.statuses[0] objectForKey:@"text"];
//更新UI需要回到主线程
// self.textView.text=text;
// [self.textView performSelectorOnMainThread:@selector(setText:) withObject:text waitUntilDone:NO];
dispatch_async(dispatch_get_main_queue(), ^{
self.textView.text =text;
});
}
更新UI需要回到主线程的方式:
不推荐:self.textView.text=text;
1.采用performSelectorOnMainThread方法
[self.textView performSelectorOnMainThread:@selector(setText:) withObject:text waitUntilDone:NO];
2. 开启一个异步操作 dispatch_async
dispatch_async(dispatch_get_main_queue(), ^{
self.textView.text =text;
});
sendAsynchronousRequest方法(在completionHandler代码块中解析JSON数据)
此方法与sendSynchronousReques方法有所不同,其中有一个参数是代码块。(这里有个小技巧是:我们可以在这个参数上按回车,Xcode会自动帮我们书写正确的代码块格式)
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
NSDictionary *dictionary=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
WeiboMode *model=[[WeiboMode alloc]initWithDictionary:dictionary];
NSString *text=[model.statuses[0] objectForKey:@"text"];
dispatch_async(dispatch_get_main_queue(), ^{
self.textView.text=text;
});
}];
}
同步Post
- (IBAction)SynchronizationPost:(UIButton *)sender {
NSString *urlString=@"https://api.weibo.com/2/statuses/update.json";
//字符串编码
urlString =[urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSURL *url=[NSURL URLWithString:urlString];
NSMutableURLRequest *mRequest=[NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60];
NSString *bodyString = @"status=|这里写我们要输入的文本数据接口|&access_token=|这里写我们获取到的API接口的access_token|";
NSData *data=[bodyString dataUsingEncoding:NSUTF8StringEncoding];
//post 设置它的方法体
[mRequest setHTTPMethod:@"POST"];
[mRequest setHTTPBody:data];
NSData *resultData=[NSURLConnection sendSynchronousRequest:mRequest returningResponse:nil error:nil];
NSDictionary *dictionary=[NSJSONSerialization JSONObjectWithData:resultData options:NSJSONReadingAllowFragments error:nil];
NSLog(@"dictionary= %@",dictionary);
}
异步Post
- (IBAction)AynchronizationPost:(UIButton *)sender {
NSString *urlString=@"https://api.weibo.com/2/statuses/update.json";
//字符串编码
urlString =[urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSURL *url=[NSURL URLWithString:urlString];
NSMutableURLRequest *mRequest=[NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60];
NSString *bodyString = @"status=|这里写我们要输入的文本数据接口|&access_token=|这里写我们获取到的API接口的access_token|";
NSData *data=[bodyString dataUsingEncoding:NSUTF8StringEncoding];
[mRequest setHTTPMethod:@"POST"];
[mRequest setHTTPBody:data];
_connectionPost=[NSURLConnection connectionWithRequest:mRequest delegate:self];
将get和post的同时写到NSURLConnectionDataDelegate协议代理的方法中
#pragma mark -------NSURLConnectionDataDelegate-------
//服务器开始响应,准备向客户发送数据
-(void)connection:(NSURLConnection *)connection
didReceiveResponse:(NSURLResponse *)response{
NSLog(@"服务器开始响应,准备向客户发送数据");
if (connection ==_connectionGet) {
_mDataGet=[NSMutableData data];
}
if (connection == _connectionPost) {
_mDataPost=[NSMutableData data];
}
}
-(void)connection:(NSURLConnection *)connection
didReceiveData:(NSData *)data{
NSLog(@"从服务器接收到数据,并且此方法会执行多次");
if (connection ==_connectionGet) {
[_mDataGet appendData:data];
}
if (connection ==_connectionPost) {
[_mDataPost appendData:data];
}
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{ NSLog(@"服务器接收数据完成");
if (connection == _connectionGet) {
NSDictionary *dictionary=[NSJSONSerialization JSONObjectWithData:_mDataGet options:NSJSONReadingAllowFragments error:nil];
WeiboMode *model=[[WeiboMode alloc]initWithDictionary:dictionary];
NSString *text=[model.statuses[0] objectForKey:@"text"];
//更新UI需要回到主线程
// self.textView.text=text;
// [self.textView performSelectorOnMainThread:@selector(setText:) withObject:text waitUntilDone:NO];
dispatch_async(dispatch_get_main_queue(), ^{
self.textView.text =text;
});
}
if (connection == _connectionPost) {
NSDictionary *dictionary=[NSJSONSerialization JSONObjectWithData:_mDataPost options:NSJSONReadingAllowFragments error:nil];
NSLog(@"dictionary = %@",dictionary);
}
}
@end