OC學習日記17 (三) get和post

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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章