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