天天看點

iOS網絡請求的使用蘋果官方API:AFNetworking:

前言:蘋果官方提供的網絡請求API有兩種: NSURLConnection、NSURLSession。

還有,目前的用的最多是主流架構:AFNetworking

iOS 7之前,隻有 NSURLConncetion

iOS 9之後,蘋果官方放棄NSURLConnection,推薦使用NSURLSession

本文将介紹iOS原生API和AFN的使用。

蘋果官方API:

以下将分别講述這兩種請求的簡單使用:

  • NSURLConnection:
-(void)demo1{
    //通路百度首頁
    
    //1. 建立一個網絡請求
    NSURL *url = [NSURL URLWithString:@"http://m.baidu.com"];
    
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    
    //2. 發送網絡請求  網絡請求是個耗時操作,在子線程發送
    
    //第一種發送網絡請求的方式
    
    /*
     * 利用 NSUrlConnection 發送一個異步的網絡請求
     *
     * @param NSURLRequest 網絡請求
     *
     * @return
     */
    //queue:操作隊列,決定網絡請求完成後的Block(completionHandler) 回調在那條線程執行
    //[NSOperationQueue mainQueue] 主線程
    //completionHandler :block 回調:網絡請求完成之後,就會自動調用這個 Block
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
        //response : 響應:伺服器的響應
        //data:二進制資料:伺服器傳回的資料。(就是我們想要的内容)
        //coonectionError:連結錯誤的資訊
        NSLog(@"網絡響應:response:%@",response);
        
        //根據傳回的二進制資料,生成字元串!NSUTF8StringEncoding:編碼方式
        NSString *html = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
        
        //在用戶端直接打開一個網頁!
        //用戶端伺服器:UIWebView
        
        //執行個體化一個用戶端浏覽器
        UIWebView *web = [[UIWebView alloc]initWithFrame:self.view.bounds];
        
        //加載html字元串:baseURL:基準的位址:相對路徑/絕對路徑
        [web loadHTMLString:html baseURL:nil];
        
        //将浏覽器加載到view上
        [self.view addSubview:web];
        
//        //在本地儲存百度首頁
//        [data writeToFile:@"/Users/Liu/Desktop/baidu.html" atomically:YES];
        
        NSLog(@"網路連結錯誤 connectionError響應:response:%@",connectionError);
    }];
}
           
  • NSURLSession:
//NSURLSession
-(void)demo2{
    //通路百度首頁
    
    //1. 建立一個網絡請求
    NSURL *url = [NSURL URLWithString:@"http://m.baidu.com"];
    
    //2.建立請求對象
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    
    //3.獲得會話對象
    NSURLSession *session=[NSURLSession sharedSession];
    
    //4.根據會話對象建立一個Task(發送請求)
    /*
     第一個參數:請求對象
     第二個參數:completionHandler回調(請求完成【成功|失敗】的回調)
     data:響應體資訊(期望的資料)
     response:響應頭資訊,主要是對伺服器端的描述
     error:錯誤資訊,如果請求失敗,則error有值
     */
    NSURLSessionDataTask *dataTask=[session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            //response : 響應:伺服器的響應
            //data:二進制資料:伺服器傳回的資料。(就是我們想要的内容)
            //error:連結錯誤的資訊
            NSLog(@"網絡響應:response:%@",response);
        
            //根據傳回的二進制資料,生成字元串!NSUTF8StringEncoding:編碼方式
            NSString *html = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
            
            //在用戶端直接打開一個網頁!
            //用戶端伺服器:UIWebView

            //将浏覽器加載到view上
            dispatch_async(dispatch_get_main_queue(), ^{
            
            //執行個體化一個用戶端浏覽器
            UIWebView *web = [[UIWebView alloc]initWithFrame:self.view.bounds];
            
            //加載html字元串:baseURL:基準的位址:相對路徑/絕對路徑
            [web loadHTMLString:html baseURL:nil];
            [self.view addSubview:web];
            
            });
        
            //        //在本地儲存百度首頁
            //        [data writeToFile:@"/Users/Liu/Desktop/baidu.html" atomically:YES];
        
        }
    ];
    
    //5.執行任務
    [dataTask resume];
}
           
  • 使用NSURLSession發送GET請求的方法和NSURLConnection類似,整個過程如下:

        1)确定請求路徑(一般由公司的背景開發人員以接口文檔的方式提供),GET請求參數直接跟在URL後面

        2)建立請求對象(預設包含了請求頭和請求方法【GET】),此步驟可以省略

        3)建立會話對象(NSURLSession)

        4)根據會話對象建立請求任務(NSURLSessionDataTask)

        5)執行Task

        6)當得到伺服器傳回的響應後,解析資料(XML|JSON|HTTP)

  • 使用NSURLSession發送POST請求的方法和NSURLConnection類似,整個過程如下:

        1)确定請求路徑(一般由公司的背景開發人員以接口文檔的方式提供)

        2)建立可變的請求對象(因為需要修改),此步驟不可以省略

        3)修改請求方法為POST

        4)設定請求體,把參數轉換為二進制資料并設定請求體

        5)建立會話對象(NSURLSession)

        6)根據會話對象建立請求任務(NSURLSessionDataTask)

        7)執行Task

        8)當得到伺服器傳回的響應後,解析資料(XML|JSON|HTTP)

//post方法   
//1.建立會話對象
    NSURLSession *session=[NSURLSession sharedSession];

    //2.根據會話對象建立task
    NSURL *url=[NSURL URLWithString:@"http://123.207.175.144/Test1.php"];

    //3.建立可變的請求對象
    NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:url];

    //4.修改請求方法為POST
    request.HTTPMethod=@"POST";

    //5.設定請求體
    request.HTTPBody=[@"Login=1" dataUsingEncoding:NSUTF8StringEncoding];

    //6.根據會話對象建立一個Task(發送請求)
         /*
                  第一個參數:請求對象
                  第二個參數:completionHandler回調(請求完成【成功|失敗】的回調)
                             data:響應體資訊(期望的資料)
                             response:響應頭資訊,主要是對伺服器端的描述
                             error:錯誤資訊,如果請求失敗,則error有值
          */
     NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error){

        //8.解析資料
        NSDictionary *dict=[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
        NSLog(@"%@",dict);
    }];

     //7.執行任務
    [dataTask resume];
           

有的時候,我們可能需要監聽網絡請求的過程(如下載下傳檔案需監聽檔案下載下傳進度),那麼就需要用到代理方法。

//代理方法
#import "ViewController.h"

@interface ViewController ()<NSURLSessionDataDelegate>
@property (nonatomic, strong) NSMutableData *responseData;
@end

@implementation ViewController

-(NSMutableData *)responseData
 {
         if (_responseData == nil) {
                 _responseData = [NSMutableData data];
             }
         return _responseData;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
     //[self performSelector:@selector(getAndSynchronousMethod)];
    [self delegateTest];
}

-(void)delegateTest
{
         //1.确定請求路徑
         NSURL *url = [NSURL URLWithString:@"http://123.207.175.144/Test1.php?Login=1"];

         //2.建立請求對象
         //請求對象内部預設已經包含了請求頭和請求方法(GET)
         NSURLRequest *request = [NSURLRequest requestWithURL:url];

         //3.獲得會話對象,并設定代理
         /*
                  第一個參數:會話對象的配置資訊defaultSessionConfiguration 表示預設配置
                  第二個參數:誰成為代理,此處為控制器本身即self
                  第三個參數:隊列,該隊列決定代理方法在哪個線程中調用,可以傳主隊列|非主隊列
                  [NSOperationQueue mainQueue]   主隊列:   代理方法在主線程中調用
                  [[NSOperationQueue alloc]init] 非主隊列: 代理方法在子線程中調用
                  */
         NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];

         //4.根據會話對象建立一個Task(發送請求)
         NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request];

         //5.執行任務
         [dataTask resume];

}

//1.接收到伺服器響應的時候調用該方法
 -(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
 {
         //在該方法中可以得到響應頭資訊,即response
         NSLog(@"didReceiveResponse--%@",[NSThread currentThread]);

         //注意:需要使用completionHandler回調告訴系統應該如何處理伺服器傳回的資料
         //預設是取消的
         /*
                     NSURLSessionResponseCancel = 0,        預設的處理方式,取消
                     NSURLSessionResponseAllow = 1,         接收伺服器傳回的資料
                     NSURLSessionResponseBecomeDownload = 2,變成一個下載下傳請求
                     NSURLSessionResponseBecomeStream        變成一個流
                  */

         completionHandler(NSURLSessionResponseAllow);
}

//2.接收到伺服器傳回資料的時候會調用該方法,如果資料較大那麼該方法可能會調用多次
 -(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
 {
         NSLog(@"didReceiveData--%@",[NSThread currentThread]);

         //拼接伺服器傳回的資料
         [self.responseData appendData:data];
}

//3.當請求完成(成功|失敗)的時候會調用該方法,如果請求失敗,則error有值
 -(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
 {
         NSLog(@"didCompleteWithError--%@",[NSThread currentThread]);

         if(error == nil)
             {
                     //解析資料
                     NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:self.responseData options:kNilOptions error:nil];
                     NSLog(@"%@",dict);
                 }
}

@end
           

如果傳回的字元有漢字,可以為NSDictionary提供一個分類,重寫系統中的方法。

//重寫Dictionary
#import "NSDictionary+Log.h"

@implementation NSDictionary (Log)
-(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
           

AFNetworking:

AFNetworking開源庫封裝了原生的方法,

iOS9.0之後,

由于NSURLConnection的棄用,

AFNetworking的使用也有一些改變。

注:使用前需要導入AFN架構:AFN架構位址
  • GET請求:
//GET請求
-(void)demo1{
    NSString *urlString = @"http://www.liubaiqi.cn";
    
    AFHTTPSessionManager *manger =[AFHTTPSessionManager manager];
    
    [manger GET:urlString parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"成功");
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"%@",error);
    }];
}
           
  • POST請求:
//POST請求
-(void)demo2{
    NSString *urlString = @"http://192.168.1.101:8080";
    
    AFHTTPSessionManager *manger =[AFHTTPSessionManager manager];
    
    NSMutableDictionary *parameter= @{@"":@"",@"":@""};
    
    [manger POST:urlString parameters:parameter progress:^(NSProgress * _NonnulluploadProgress){
        
    }success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"成功");
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"%@",error);
    }];
}
           
  • Download請求:
//DownLoad請求
-(void)demo3{
    //1. 建立NSURLSessionConfiguration
    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    
    //2. 建立管理者對象
    AFURLSessionManager *manager = [[AFURLSessionManager alloc]initWithSessionConfiguration:configuration];
    
    //3. 設定url
    NSURL *url = [NSURL URLWithString:@"http://127.0.0.1/1.mp4"];
    
    //4. 建立請求對象
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    
    //5. 下載下傳任務
    NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
        //列印下載下傳進度
        NSLog(@"%lf",*downloadProgress.completedUnitCount/downloadProgress.totalUnitCount);
        
    } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
        //設定下載下傳路徑
        NSURL *documentsDirectoryURL = [[NSFileManager defaultManager]URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
        
        return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];
        
    } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
        //下載下傳完成
        NSLog(@"File downloaded to : %@",filePath);
    }];
    //啟動任務
    [downloadTask resume];
}
           
  • Upload請求:
//UpLoad請求
-(void)demo4{
    //建立NSURLSessionConfiguration
    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    
    //建立管理者對象
    AFURLSessionManager *manager = [[AFURLSessionManager alloc]initWithSessionConfiguration:configuration];
    
    //設定url
    NSURL *url = [NSURL URLWithString:@"http://127.0.0.1"];
    //建立請求對象
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    //檔案路徑
    NSURL *filePath = [NSURL fileURLWithPath:@"file://Users/Liu/Desktop/Note"];
    
    //上傳任務
    NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithRequest:request fromFile:filePath progress:nil completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {
        if(error){
            //錯誤
            NSLog(@"Error:%@",error);
        }else{
            //成功
            NSLog(@"Success %@ %@",response,responseObject);
        }
    }];
    //啟動任務
    [uploadTask resume];
}
           
  • 網絡狀态:
//網絡狀态
-(void)demo5{
    //1. 建立網絡監測者
    AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager];
    
    [manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
        //監測網絡改變
        switch (status) {
            case AFNetworkReachabilityStatusUnknown:
                NSLog(@"未知網絡狀态");
                break;
            case AFNetworkReachabilityStatusNotReachable:
                NSLog(@"無網絡");
                break;
            case AFNetworkReachabilityStatusReachableViaWWAN:
                NSLog(@"蜂窩資料網絡");
                break;
            case AFNetworkReachabilityStatusReachableViaWiFi:
                NSLog(@"WiFi網絡");
                break;
                
            default:
                break;
        }
    }];
}
           

本文參考了組長的blog,以及自己學習時整理的一些小demo。

如果有錯誤,希望各位大神指出,我修改。

作者:MrLiuQ

連結:https://www.jianshu.com/p/c34f0740f178

來源:簡書