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:];
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: ];
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[] 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:];
伺服器連接配接
伺服器連接配接有兩種方法,我們可以用協定代理的方法或直接請求的方法
用代理的方法伺服器連接配接
(如果将異步的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[] 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 *[email protected]"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:];
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 *[email protected]"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:];
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[] 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