iOS 原生NSURLSession 簡單的 GET、POST 請求

//  WsqflyNetWorking.h

//  WSQNetWorkingSystem

//

//  Created by webapps on 16/12/28.

//  Copyright © 2016 webapps. All rights reserved.


#import <Foundation/Foundation.h>

#import <UIKit/UIKit.h>


typedef void(^SuccessBlock)(id response);                                 // 成功返回的數據

typedef void(^RequestHeadBlock)(id response);                            // 請求頭返回的數據

typedef void(^FaileBlock)(NSError * error);                             // 請求錯誤返回的數據




typedef NS_ENUM(NSUInteger,WsqflyNetSessionMaskState) {

    

    WsqflyNetSessionMaskStateNone       =  0,                      // 沒有菊花

    WsqflyNetSessionMaskStateCanTouch   =  1,                     // 有菊花並點擊屏幕有效

    WsqflyNetSessionMaskStateNotTouch   =  2                     // 有菊花單點擊屏幕沒有效果

  

};


typedef NS_ENUM(NSUInteger,WsqflyNetSessionResponseType){

    WsqflyNetSessionResponseTypeDATA    =  0,                // 返回後臺是什麼就是什麼DATA

    WsqflyNetSessionResponseTypeJSON    =  1                // 返會序列化後的JSON數據

};




@interface WsqflyNetSession : NSObject


//單利

+ (instancetype) wsqflyNetWorkingShare;


//判斷是否有網絡

//+ (NSString *)connectedToNetwork;



/**GET短數據請求

 * urlString          網址

 * param              參數

 * state              顯示菊花的類型

 * backData           返回的數據是NSDATA還是JSON

 * successBlock       成功數據的block

 * faileBlock         失敗的block

 * requestHeadBlock   請求頭的數據的block

 */

- (void)get1:(NSString *)urlString param:(NSDictionary *)param maskState:(WsqflyNetSessionMaskState)state backData:(WsqflyNetSessionResponseType)backData success:(SuccessBlock)successBlock requestHead:(RequestHeadBlock)requestHeadBlock faile:(FaileBlock)faileBlock;



/**POST短數據請求

 * urlString           網址

 * param               參數

 * state               顯示菊花的類型

 * backData            返回的數據是NSDATA還是JSON

 * successBlock        成功數據的block

 * faileBlock          失敗的block

 * requestHeadBlock    請求頭的數據的block

 */


-(void)post:(NSString *)urlString bodyparam:(NSDictionary *)param maskState:(WsqflyNetSessionMaskState)state backData:(WsqflyNetSessionResponseType)backData success:(SuccessBlock)successBlock requestHead:(RequestHeadBlock)requestHeadBlock faile:(FaileBlock)faileBlock;




//

//  WsqflyNetWorking.m

//  WSQNetWorkingSystem

//

//  Created by webapps on 16/12/28.

//  Copyright © 2016 webapps. All rights reserved.

//


#import "WsqflyNetSession.h"

#import "RealReachability.h"


#define CONTECTTIME  30  // 聯網時間


@interface WsqflyNetSession ()


@property (nonatomic,strong)UIActivityIndicatorView * wsqAView;

@property (nonatomic,assign)int maskCount;


@end




@implementation WsqflyNetSession



static id _instance;

+ (instancetype)allocWithZone:(struct_NSZone *)zone

{

    staticdispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        _instance = [superallocWithZone:zone];

    });

    return_instance;

}


+ (instancetype)wsqflyNetWorkingShare

{

    staticdispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        _instance = [[selfalloc] init];

    });

    return_instance;

}


- (instancetype)init{

    

    if (self = [superinit]) {

        _wsqAView = [[UIActivityIndicatorViewalloc] initWithFrame:[UIScreenmainScreen].bounds];

        _wsqAView.color = [UIColorblackColor];

    }

    returnself;

}



#pragma mrak 判斷是否聯網

//+ (NSString *)connectedToNetwork

//{

//    NSString *netString;

//    ReachabilityStatus status = [GLobalRealReachability currentReachabilityStatus];

//    

//    switch (status) {

//        case -1:

//            netString = @"網絡異常!";

//            break;

//        case 0:

//            netString = @"連接不到網絡!";

//            break;

//        case 1:

//            netString = @"正在使用流量上網!";

//            break;

//        case 2:

//            netString = @"正在使用wifi上網!";

//            break;

//            

//        default:

//            break;

//    }

//    return netString;

//}



#pragma MARK-- GET


- (void)get1:(NSString *)urlString param:(NSDictionary *)param maskState:(WsqflyNetSessionMaskState)state backData:(WsqflyNetSessionResponseType)backData success:(SuccessBlock)successBlock requestHead:(RequestHeadBlock)requestHeadBlock faile:(FaileBlock)faileBlock{

    

    NSURL *url;

    

 

    NSString *string = [NSStringstring];

    if (param) {//帶字典參數

        string = [selfnsdictionaryToNSStting:param];

        

           //1. GET 請求,直接把請求參數跟在URL的後面以?(問號前是域名與/接口名)隔開,多個參數之間以&符號拼接

         url = [NSURLURLWithString:[selfurlConversionFromOriginalURL:[NSStringstringWithFormat:@"%@&%@",urlString,string]]];

    }else{

           //1. GET 請求,直接把請求參數跟在URL的後面以?(問號前是域名與/接口名)隔開,多個參數之間以&符號拼接

        url = [NSURLURLWithString:[selfurlConversionFromOriginalURL:urlString]];

    }


    //2. 創建請求對象內部默認了已經包含了請求頭和請求方法(GET)的對象

      NSMutableURLRequest *request = [[NSMutableURLRequestalloc] initWithURL:urlcachePolicy:NSURLRequestUseProtocolCachePolicytimeoutInterval:CONTECTTIME];

    

    /*   設置請求頭  */

//    [request setValue:@"92b5787ecd17417b718a2aaedc7e6ce8" forHTTPHeaderField:@"apix-key"];

    

    //4. 根據會話對象創建一個task任務(發送請求)

    

    [selfstartNSURLSessionDataTask:requestmaskState:state responType:backDatasuccess:successBlock headfiles:requestHeadBlock fail:faileBlock];

    

}





#pragma MARK-- POST


-(void)post:(NSString *)urlString bodyparam:(NSDictionary *)param maskState:(WsqflyNetSessionMaskState)state backData:(WsqflyNetSessionResponseType)backData success:(SuccessBlock)successBlock requestHead:(RequestHeadBlock)requestHeadBlock faile:(FaileBlock)faileBlock{

    

    //POST請求需要修改請求方法爲POST,並把參數轉換爲二進制數據設置爲請求體

    

  

    

    //1.url

    NSURL *url = [NSURLURLWithString:[selfurlConversionFromOriginalURL:urlString]];

    

    //2.創建可變的請求對象

    NSMutableURLRequest *request = [[NSMutableURLRequestalloc] initWithURL:urlcachePolicy:NSURLRequestUseProtocolCachePolicytimeoutInterval:CONTECTTIME];


    /*   設置請求頭  */

    //    [request setValue:@"92b5787ecd17417b718a2aaedc7e6ce8" forHTTPHeaderField:@"apix-key"];

    

    

    

    //4.修改請求方法爲POST

    request.HTTPMethod =@"POST";

    

    

    //有參數請求題

    if (param) {

        

        //5.設置請求體

        NSString *string = [selfnsdictionaryToNSStting:param];

        request.HTTPBody = [stringdataUsingEncoding:NSUTF8StringEncoding];

    }

    

    

    //6.根據會話對象創建一個Task(發送請求)

    [selfstartNSURLSessionDataTask:requestmaskState:state responType:backDatasuccess:successBlock headfiles:requestHeadBlock fail:faileBlock];

}





#pragma MARK-- 根據會話對象創建一個Task(發送請求)


- (void)startNSURLSessionDataTask:(NSMutableURLRequest *)request  maskState:(WsqflyNetSessionMaskState)state responType:(WsqflyNetSessionResponseType)responType success:(SuccessBlock)respone headfiles:(RequestHeadBlock)headfiles fail:(FaileBlock)fail{

    

    

    

    //3.創建會話對象

    NSURLSession *session = [NSURLSessionsharedSession];

    

    /*

     第一個參數:請求對象

     第二個參數:completionHandler回調(請求完成【成功|失敗】的回調)

     data:響應體信息(期望的數據)

     response:響應頭信息,主要是對服務器端的描述

     error:錯誤信息,如果請求失敗,則error有值

     */

    NSURLSessionDataTask *dataTask = [sessiondataTaskWithRequest:requestcompletionHandler:^(NSData *_Nullable data, NSURLResponse *_Nullable response, NSError * _Nullable error) {

        

        [selfstopAnimation:state];

        

        NSString *result = [[NSStringalloc] initWithData:data encoding:NSUTF8StringEncoding];

        NSLog(@"result:%@",result);

        

        // 解析服務器返回的數據(返回的數據爲JSON格式,因此使用NSJNOSerialization進行反序列化)

        id dict = [NSJSONSerializationJSONObjectWithData:data options:NSJSONReadingMutableLeaveserror:nil];

        

        NSLog(@"response%@",response);

        NSHTTPURLResponse * da =(NSHTTPURLResponse *)response;

        NSDictionary *allheadsFiles = da.allHeaderFields;

        NSLog(@"allheadsFiles:%@",allheadsFiles[@"Content-Type"]);

        

        //8.解析數據

        if (!error) {

            if (responType ==WsqflyNetSessionResponseTypeJSON) {//返回JSON

                respone(dict);

            }else{

                   respone(data);//返回二進制

            }

            

            

        }else{

            fail(error);

            NSLog(@"網絡請求失敗");

        }

        

        if (response) {

            headfiles(allheadsFiles);

        }

        

    }];

    

    //7.執行任務

    [selfshowAnimation:state];

    [dataTask resume];

}





#pragma MARK -- 菊花

// 添加菊花

- (void)showAnimation:(WsqflyNetSessionMaskState)maskType {

    if (maskType !=WsqflyNetSessionMaskStateNone) {  // 有菊花動畫

        dispatch_async(dispatch_get_main_queue(), ^{

            [UIApplicationsharedApplication].networkActivityIndicatorVisible =true;

            [[UIApplicationsharedApplication].keyWindowaddSubview:_wsqAView];

            _wsqAView.hidden =NO;

            [_wsqAViewstartAnimating];

            _wsqAView.userInteractionEnabled = (maskType ==WsqflyNetSessionMaskStateNotTouch ?YES : NO);

            _maskCount++;

        });

    }

}

// 移除菊花

- (void)stopAnimation:(WsqflyNetSessionMaskState)maskType {

    if (maskType !=WsqflyNetSessionMaskStateNone) {

        dispatch_async(dispatch_get_main_queue(), ^{

            _maskCount--;

            if (_maskCount <=0) {

                [UIApplicationsharedApplication].networkActivityIndicatorVisible =false;

                [_wsqAViewstopAnimating];

                _wsqAView.hidden =YES;

                [_wsqAViewremoveFromSuperview];

            }

        });

    }

}




#pragma MARK -- 把字典拼成字符串


- (NSString *) nsdictionaryToNSStting:(NSDictionary *)param{

    

    NSMutableString *string = [NSMutableStringstring];

    

    //便利字典把鍵值平起來

    [param enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL *_Nonnull stop) {

        [string appendFormat:@"%@:",key];

        [string appendFormat:@"%@",obj];

        [string appendFormat:@"%@",@"&"];

    }];

    // 去掉最後一個&

    NSRange rangeLast = [stringrangeOfString:@"&"options:NSBackwardsSearch];

    if (rangeLast.length !=0) {

        [string deleteCharactersInRange:rangeLast];

    }

    NSLog(@"string:%@",string);

    NSRange range =NSMakeRange(0, [stringlength]);

    [string replaceOccurrencesOfString:@":"withString:@"="options:NSCaseInsensitiveSearchrange:range];

    NSLog(@"string:%@",string);

    

    return string;

}



// 如果URL有中文,轉換成百分號

- (NSString *)urlConversionFromOriginalURL:(NSString *)originalURL {

    

    if ([[UIDevicecurrentDevice].systemVersionfloatValue] < 9.0) {

        return [originalURLstringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];// iOS 9.0以下

    }

    return [originalURLstringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSetURLQueryAllowedCharacterSet]];

}




#pragma mark NSURLSession Delegate

/* 收到身份驗證 ssl */

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition,NSURLCredential * _Nullable))completionHandler {

    

    NSLog(@"didReceiveChallenge %@", challenge.protectionSpace);

    NSLog(@"調用了最外層");

    // 1.判斷服務器返回的證書類型,是否是服務器信任

    if ([challenge.protectionSpace.authenticationMethodisEqualToString:NSURLAuthenticationMethodServerTrust]) {       NSLog(@"調用了裏面這一層是服務器信任的證書");

        /*  NSURLSessionAuthChallengeUseCredential = 0,                    使用證書         NSURLSessionAuthChallengePerformDefaultHandling = 1,           忽略證書(默認的處理方式)         NSURLSessionAuthChallengeCancelAuthenticationChallenge = 2,     忽略書證,並取消這次請求         NSURLSessionAuthChallengeRejectProtectionSpace = 3,           拒絕當前這一次,下一次再詢問   

         */

        

        NSURLCredential *card = [[NSURLCredentialalloc]initWithTrust:challenge.protectionSpace.serverTrust];

        completionHandler(NSURLSessionAuthChallengeUseCredential , card);

        

    }

   

}





@end



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