AFNetworking使用

AFN基本使用

GET請求:

-(void)get1
{
    // 1.創建AFHTTPSessionManager管理者
    // AFHTTPSessionManager內部是基於NSURLSession實現的
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

    // 2.發送請求
    NSDictionary *param = @{
                            @"username":@"520it",
                            @"pwd":@"520it"
                            };

    // 注意:responseObject:請求成功返回的響應結果(AFN內部已經把響應體轉換爲OC對象,通常是字典或數組)
    /*
        第一個參數:請求路徑(不包含參數)
        第二個參數:字典(發送給服務器的參數)
        第三個參數:成功的回調
    */
    [manager GET:@"http://120.25.226.186:32812/login" parameters:param success:^(NSURLSessionDataTask * _Nonnull task, id  _Nonnull responseObject) {
         //task裏面包含了響應頭信息
         NSLog(@"請求成功---%@",[responseObject class]);

    } failure:^(NSURLSessionDataTask * _Nonnull task, NSError * _Nonnull error) {
        NSLog(@"失敗---%@",error);
    }];
  }
}
-(void)post1
{
    // 1.創建AFHTTPSessionManager管理者
    // AFHTTPSessionManager內部是基於NSURLSession實現的
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

    // 2.發送請求
    NSDictionary *param = @{
                            @"username":@"520it",
                            @"pwd":@"520it"
                            };

    // 注意:responseObject:請求成功返回的響應結果(AFN內部已經把響應體轉換爲OC對象,通常是字典或數組)
    /*
        第一個參數:請求路徑(不包含參數)
        第二個參數:字典(發送給服務器的參數)
        第三個參數:成功的回調
    */
    [manager POST:@"http://120.25.226.186:32812/login" parameters:param success:^(NSURLSessionDataTask * _Nonnull task, id  _Nonnull responseObject) {
         //task裏面包含了響應頭信息
         NSLog(@"請求成功---%@",[responseObject class]);

    } failure:^(NSURLSessionDataTask * _Nonnull task, NSError * _Nonnull error) {
        NSLog(@"失敗---%@",error);
    }];
  }
}

AFN實現文件下載


-(void)download
{
    //1.創建一個管理者
    AFHTTPSessionManager *manage  = [AFHTTPSessionManager manager];

    //2.下載文件
    /*
     第一個參數:請求對象
     第二個參數:下載進度
     第三個參數:block回調,需要返回一個url地址,用來告訴AFN下載文件的目標地址
         targetPath:AFN內部下載文件存儲的地址,tmp文件夾下
         response:請求的響應頭
         返回值:文件應該剪切到什麼地方
     第四個參數:block回調,當文件下載完成之後調用
        response:響應頭
        filePath:文件存儲在沙盒的地址 == 第三個參數中block的返回值
        error:錯誤信息
     */

    //2.1 創建請求對象
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://120.25.226.186:32812/resources/images/minion_02.png"]];

    //2.2 創建下載進度,並監聽
    NSProgress *progress = nil;

    NSURLSessionDownloadTask *downloadTask = [manage downloadTaskWithRequest:request progress:&progress destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {

        NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];

        //拼接文件全路徑
        NSString *fullpath = [caches stringByAppendingPathComponent:response.suggestedFilename];
        NSURL *filePathUrl = [NSURL fileURLWithPath:fullpath];
        return filePathUrl;

    } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nonnull filePath, NSError * _Nonnull error) {

        NSLog(@"文件下載完畢---%@",filePath);
    }];

    //2.3 使用KVO監聽下載進度
    [progress addObserver:self forKeyPath:@"completedUnitCount" options:NSKeyValueObservingOptionNew context:nil];

    //3.啓動任務
    [downloadTask resume];
}

//獲取並計算當前文件的下載進度
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(NSProgress *)progress change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
    NSLog(@"%zd--%zd--%f",progress.completedUnitCount,progress.totalUnitCount,1.0 * progress.completedUnitCount/progress.totalUnitCount);
}

文件上傳:

-(void)upload
{
    //1.創建一個請求管理者
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

    //2.發送POST請求上傳數據
    /*
     第一個參數:請求路徑:NSString類型
     第二個參數:要上傳的非文件參數
     第三個參數:block回調
        在該回調中,需要利用formData拼接即將上傳的二進制數據
     第三個參數:上傳成功的block回調
        task:dataTask(任務)
        responseObject:服務器返回的數據
     第四個參數:上傳失敗的block回調
        error:錯誤信息,如果上傳文件失敗,那麼error裏面包含了錯誤的描述信息
     */

    NSDictionary *dict = @{
                           @"username":@"wenidngding"
                           };

    [manager POST:@"http://120.25.226.186:32812/upload" parameters:dict constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {

        //把本地的圖片轉換爲NSData類型的數據
        UIImage *image = [UIImage imageNamed:@"123"];
        NSData *data = UIImagePNGRepresentation(image);

        /*
         //拼接二進制文件數據
         第一個參數:要上傳的文件的二進制數據
         第二個參數:服務器接口規定的名稱
         第三個參數:這個參數上傳到服務器之後用什麼名字來進行保存
         第四個參數:上傳文件的MIMEType類型
         */
        [formData appendPartWithFileData:data name:@"file" fileName:@"xxoo.png" mimeType:@"application/octet-stream"];

    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nonnull responseObject) {
        NSLog(@"請求成功---%@",responseObject);

    } failure:^(NSURLSessionDataTask * _Nonnull task, NSError * _Nonnull error) {
        NSLog(@"請求失敗--%@",error);
    }];
}

-(void)upload2
{
    NSLog(@"%s",__func__);

    //1.創建一個請求管理者
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

    //2.發送POST請求上傳數據
    /*
     第一個參數:請求路徑:NSString類型
     第二個參數:要上傳的非文件參數
     第三個參數:block回調
     在該回調中,需要利用formData拼接即將上傳的二進制數據
     第三個參數:上傳成功的block回調
     task:dataTask(任務)
     responseObject:服務器返回的數據
     第四個參數:上傳失敗的block回調
     error:錯誤信息,如果上傳文件失敗,那麼error裏面包含了錯誤的描述信息
     */

    NSDictionary *dict = @{
                           @"username":@"wenidngding"
                           };

    [manager POST:@"http://120.25.226.186:32812/upload" parameters:dict constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {

        //本地文件的url
        NSURL *fileUrl = [NSURL fileURLWithPath:@"/Users/文頂頂/Desktop/KF[WTI`AQ3T`A@3R(B96D89.gif"];
        /*
         //拼接二進制文件數據
         第一個參數:要上傳文件的url路徑
         第二個參數:服務器要求的參數名稱
         第三個參數:這個文件上傳到服務器之後叫什麼名稱
         第四個參數:文件的mimetype類型
         第五個參數:錯誤信息
         */
//        [formData appendPartWithFileURL:fileUrl name:@"file" fileName:@"xx.png" mimeType:@"application/octet-stream" error:nil];

        //另外一種上傳文件的方式
        /*
         說明:該方法和上面的方法等價,不過該方法更加簡單其內部會自動的的根據url路徑確定文件保存名稱,並通過內部方法獲取上傳文件的mimetype類型
         */
        [formData appendPartWithFileURL:fileUrl name:@"file" error:nil];

    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nonnull responseObject) {
        NSLog(@"請求成功---%@",responseObject);

    } failure:^(NSURLSessionDataTask * _Nonnull task, NSError * _Nonnull error) {
        NSLog(@"請求失敗--%@",error);
    }];
}

AFN使用技巧

1.在開發的時候可以創建一個工具類,繼承自我們的AFN中的請求管理者,在控制器中真正發請求的代碼使用自己封裝的工具類。
2.這樣做的優點是以後如果修改了底層依賴的框架,那麼我們修改這個工具類就可以了,而不用再一個一個的去修改。
3.該工具類一般提供一個單例方法,在該方法中會設置一個基本的請求路徑。
4.該方法通常還會提供對GET或POST請求的封裝。
5.在外面的時候通過該工具類來發送請求
6.單例方法:

+ (instancetype)shareNetworkTools
{
    static XMGNetworkTools *instance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        // 注意: BaseURL中一定要以/結尾
        instance = [[self alloc] initWithBaseURL:[NSURL URLWithString:@"http://120.25.226.186:32812/"]];
    });
    return instance;
}

AFN序列化相關

AFN它內部默認把服務器響應的數據當做json來進行解析,所以如果服務器返回給我的不是JSON數據那麼請求報錯,這個時候需要設置AFN對響應信息的解析方式。

AFN提供了三種解析響應信息的方式,分別是:
1)AFXMLParserResponseSerializer----XML
2) AFHTTPResponseSerializer---------默認二進制響應數據
3)AFJSONResponseSerializer---------JSON

還有一種情況就是服務器返回給我們的數據格式不太一致(開發者工具Content-Type:text/html),那麼這種情況也有可能請求不成功。解決方法:
1) 直接在源代碼中修改,添加相應的Content-Type
2) 拿到這個屬性,添加到它的集合中

xml解析

-(void)srializer
{
    //1.創建請求管理者,內部基於NSURLSession
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

    /* 知識點1:設置AFN採用什麼樣的方式來解析服務器返回的數據*/

    //如果返回的是XML,那麼告訴AFN,響應的時候使用XML的方式解析
    manager.responseSerializer = [AFXMLParserResponseSerializer serializer];

    //如果返回的就是二進制數據,那麼採用默認二進制的方式來解析數據
    //manager.responseSerializer = [AFHTTPResponseSerializer serializer];

    //採用JSON的方式來解析數據
    //manager.responseSerializer = [AFJSONResponseSerializer serializer];

    /*知識點2 告訴AFN,再序列化服務器返回的數據的時候,支持此種類型
    [AFJSONResponseSerializer serializer].acceptableContentTypes = [NSSet setWithObject:@"text/html"];

    // 2.把所有的請求參數通過字典的方式來裝載,GET方法內部會自動把所有的鍵值對取出以&符號拼接並最後用?符號連接在請求路徑後面
    NSDictionary *dict = @{
                           @"username":@"223",
                           @"pwd":@"ewr",
                           @"type":@"XML"
                           };

    //3.發送GET請求
    [manager GET:@"http://120.25.226.186:32812/login" parameters:dict success:^(NSURLSessionDataTask * _Nonnull task, id  _Nonnull responseObject) {

        //4.請求成功的回調block
        NSLog(@"%@",[responseObject class]);

    } failure:^(NSURLSessionDataTask * _Nonnull task, NSError * _Nonnull error) {

        //5.請求失敗的回調,可以打印error的值查看錯誤信息
        NSLog(@"%@",error);
    }];
}

html解析

-(void)html
{
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

    //有三種方式解析,需要手動設置AFN裏面的方法???
    //content-type: text/html"
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/html"];

    //2.發送請求
    [manager GET:@"http://www.baidu.com" parameters:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nonnull responseObject) {

        NSLog(@"請求成功---%@",[[NSString alloc]initWithData:responseObject encoding:NSUTF8StringEncoding]);

    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"請求失敗---%@",error);
    }];
}

監聽網絡狀態的改變 AFNetworkReachabilityManager

//1.獲得網絡監測管理者
    AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager];

    //2.檢測
    /*
     AFNetworkReachabilityStatusUnknown          = 未知
     AFNetworkReachabilityStatusNotReachable     = 沒有網絡
     AFNetworkReachabilityStatusReachableViaWWAN = 蜂窩網絡
     AFNetworkReachabilityStatusReachableViaWiFi = WIFI
     */
    [manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {

        switch (status) {
            case AFNetworkReachabilityStatusUnknown:
                NSLog(@"未知-----");
                break;
            case AFNetworkReachabilityStatusNotReachable:
                NSLog(@"沒有網絡");
                break;
            case AFNetworkReachabilityStatusReachableViaWWAN:
                NSLog(@"3G");
                break;
            case AFNetworkReachabilityStatusReachableViaWiFi:
                NSLog(@"wifi");
                break;

            default:
                break;
        }
    }];

    //3.開始監聽  要監控網絡連接狀態,必須要先調用單例的startMonitoring方法
    [manager startMonitoring];

蘋果原生的監聽
使用蘋果提供的Reachability來檢測網絡狀態,如果要持續監聽網絡狀態的變化,需要結合通知一起使用。

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //1.註冊一個通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkChange) name:kReachabilityChangedNotification object:nil];

    //2.拿到一個對象,然後調用開始監聽方法
    Reachability *r = [Reachability reachabilityForInternetConnection];
    [r startNotifier];

    //持有該對象,不要讓該對象釋放掉
    self.r = r;
}

//當控制器釋放的時候,移除通知的監聽
-(void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [self.r stopNotifier];
}

-(void)networkChange
{
    //獲取當前網絡的狀態
   if ([Reachability reachabilityForInternetConnection].currentReachabilityStatus == ReachableViaWWAN)
    {
        NSLog(@"當前網絡狀態爲3G");
        return;
    }

    if ([Reachability reachabilityForLocalWiFi].currentReachabilityStatus == ReachableViaWiFi)
    {
        NSLog(@"當前網絡狀態爲wifi");
        return;
    }

    NSLog(@"當前沒有網絡");
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章