[10分鐘教你]封裝iOS網絡服務

聯(lián)系方式:401518215@qq.com

童稚們,我有回來了> <。感覺上次寫的教程反響還是挺好的限番,我動力十足呀扼褪。今天我也來帶給大家在iOS項目開發(fā)里面必須的技能--網絡請求想幻。當然啦,普通的網絡請求寫起來不困難话浇,本來就屬于iOS開發(fā)的必修課程脏毯,不過現(xiàn)在我們需要考慮的是處于項目開發(fā)的環(huán)境下,自然就少不了對網絡服務的封裝幔崖,不然我們在項目的使用過程中就變得異常的混亂和長~~~~食店。

不多說渣淤,我們先要導入一個輪子:AFNetworking。不得不說這個第三方庫的功能實在強大叛买,今天我們使用到的網絡請求功能也不過是這個庫的鳳毛麟角砂代,想要仔細學習的話可以自己去看一下。導入方式不多說:拷貝或者cocoapod率挣。

必須說明的是AFNetworking其實已經把網絡請求給封裝一次了刻伊,那為什么我們還要封裝一次呢?只是為了統(tǒng)一我們的請求接口和使用于我們項目的實質需求椒功。畢竟別人封裝考慮的是全面和實用捶箱,而我們在他們的基礎上再次封裝則是為了我們的項目開發(fā)需求。

說了這么多动漾,終于要上代碼了丁屎。先創(chuàng)建兩個網絡服務類
typedef NS_ENUM(NSUInteger, HttpRequestType) {
    
    //get請求
    HttpRequestType_Get = 0,
    //post請求
    HttpRequestType_Post
};

typedef NS_ENUM(NSInteger, AFNetworkErrorType) {
    AFNetworkErrorType_TimeOut = NSURLErrorTimedOut,                  //連接超時
    AFNetworkErrorType_UnURL = NSURLErrorUnsupportedURL,              //無URL
    AFNetworkErrorType_NoNetwork = NSURLErrorNotConnectedToInternet,  //無網絡
    AFNetworkErrorType_404Failed = NSURLErrorBadServerResponse,       //404
    AFNetworkErrorType_3840Failed = 3840                              //網絡錯誤
};

@interface CHHttpRequest : NSObject

/**
 *   發(fā)送get請求
 *
 *   @param  URLString  請求的網址字符串
 *   @param  parameters 請求的參數
 *   @param  success    請求成功的回調
 *   @param  failure    請求失敗的回調
 */

+(void)getWithURLString:(NSString*)URLString
             parameters:(id)parameters
                success:(void(^)(id responerObject))success
                failure:(void(^)(NSError* error))failure;


/**
 *   發(fā)送post請求
 *
 *   @param  URLString  請求的網址字符串
 *   @param  parameters 請求的參數
 *   @param  success    請求成功的回調
 *   @param  failure    請求失敗的回調
 */
+(void)postWithURLString:(NSString*)URLString
              parameters:(id)parameters
                 success:(void(^)(id responerObject))success
                 failure:(void(^)(NSError *error))failure;

/**
 *   發(fā)送網絡請求
 *
 *   @param  URLString  請求的網址字符串
 *   @param  parameters 請求的參數
 *   @param  type       請求的類型
 *   @param  success    請求成功的回調
 *   @param  failure    請求失敗的回調
 */

+(void)requestWithURLString:(NSString*)URLString
                 parameters:(id)parameters
                       type:(HttpRequestType)type
                    success:(void(^)(id responseObject))success
                    failure:(void(^)(NSError* error))failure;


/**
 *   上傳圖片
 *
 *   @param  URLString  請求的網址字符串
 *   @param  parameters 請求的參數
 *   @param  uploadParam上傳圖片的信息
 *   @param  success    請求成功的回調
 *   @param  failure    請求失敗的回調
 */

+(void)uploadWithURLString:(NSString *)URLString
                parameters:(id)parameters
               uploadParam:(CHUploadParam*)uploadParam
                   success:(void(^)())success
                   failure:(void(^)(NSError* error))failure;

@end

#import "CHHttpRequest.h"
#import "AFNetworking.h"
#import "CHUploadParam.h"

@implementation CHHttpRequest

#pragma mark -- GET請求
+(void)getWithURLString:(NSString *)URLString parameters:(id)parameters success:(void (^)(id))success failure:(void (^)(NSError *))failure
{
    AFHTTPSessionManager* manager = [AFHTTPSessionManager manager];
    //可以接受的類型
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    //請求隊列的最大并發(fā)數
    //manager.operationQueue.maxConcurrentOperationCount = 5;
    //請求超時的時間
    //manager.requestSerializer.timeoutInterval = 5;
    
    [manager GET:URLString parameters:nil progress:nil success:^(NSURLSessionDataTask* _Nonnull task,id _Nullable responseObject) {
        //請求成功
        success(responseObject);
    }failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        //請求失敗
        if (failure) {
            failure(error);
            //輸出網絡診斷信息
            __weak id weakSelf = self;
            [weakSelf requestFailure:error];
        }
    }];
}

#pragma mark -- POST請求
+(void)postWithURLString:(NSString *)URLString parameters:(id)parameters success:(void (^)(id))success failure:(void (^)(NSError *))failure
{
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    //請求隊列的最大并發(fā)數
    //manager.operationQueue.maxConcurrentOperationCount = 5;
    //請求超時的時間
    //manager.requestSerializer.timeoutInterval = 5;
    
    [manager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        //請求成功
        success(responseObject);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        //請求失敗
        if (failure) {
            failure(error);
            //輸出網絡診斷信息
            __weak id weakSelf = self;
            [weakSelf requestFailure:error];
        }
    }];
}

#pragma mark -- REQUEST請求
+(void)requestWithURLString:(NSString *)URLString parameters:(id)parameters type:(HttpRequestType)type success:(void (^)(id))success failure:(void (^)(NSError *))failure
{
    AFHTTPSessionManager* manager = [AFHTTPSessionManager manager];
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    //請求隊列的最大并發(fā)數
    //manager.operationQueue.maxConcurrentOperationCount = 5;
    //請求超時的時間
    //manager.requestSerializer.timeoutInterval = 5;
    
    switch (type) {
        case HttpRequestType_Get:
        {
            [manager GET:URLString parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                //請求成功
                success(responseObject);
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                //請求失敗
                if (failure) {
                    failure(error);
                    //輸出網絡診斷信息
                    __weak id weakSelf = self;
                    [weakSelf requestFailure:error];
                }
            }];
        }
            break;
            
        case HttpRequestType_Post:
        {
            [manager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                //請求成功
                success(responseObject);
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                //請求失敗
                if (failure) {
                    failure(error);
                    //輸出網絡診斷信息
                    __weak id weakSelf = self;
                    [weakSelf requestFailure:error];
                }
            }];
        }
            break;
    }
}

#pragma mark -- 上傳圖片
+(void)uploadWithURLString:(NSString *)URLString parameters:(id)parameters uploadParam:(CHUploadParam *)uploadParam success:(void (^)())success failure:(void (^)(NSError *))failure
{
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    //請求隊列的最大并發(fā)數
    //manager.operationQueue.maxConcurrentOperationCount = 5;
    //請求超時的時間
    //manager.requestSerializer.timeoutInterval = 5;
    
    [manager POST:URLString parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        [formData appendPartWithFileData:uploadParam.data name:uploadParam.name fileName:uploadParam.fileName mimeType:uploadParam.mimeType];
    } progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        //請求成功
        success(responseObject);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        //請求失敗
        if (failure) {
            failure(error);
            //輸出網絡診斷信息
            __weak id weakSelf = self;
            [weakSelf requestFailure:error];
        }
    }];
}

#pragma mark -- requestFailure
-(void)requestFailure:(NSError *)error
{
    switch (error.code) {
        case AFNetworkErrorType_TimeOut:
            NSLog(@"網絡連接超時");
            break;
            
        case AFNetworkErrorType_UnURL:
            NSLog(@"沒有找到該網絡地址");
            break;
            
        case AFNetworkErrorType_NoNetwork:
            NSLog(@"沒有網絡服務");
            break;
            
        case AFNetworkErrorType_404Failed:
            NSLog(@"404網絡原因");
            break;
            
        case AFNetworkErrorType_3840Failed:
            NSLog(@"服務器出錯");
            break;
        default:
            NSLog(@"不明原因");
            break;
    }
}

@end
有個CHUploadParam的類是用來處理圖片上傳的,大家也要創(chuàng)建這個類的.h/.m旱眯,代碼如下:
@interface CHUploadParam : NSObject
//圖片二進制數據
@property (nonatomic,strong) NSData * data;
//服務器對應的參數名稱
@property (nonatomic,copy) NSString * name;
//文件的名稱
@property (nonatomic,copy) NSString * fileName;
//文件的MIME類型
@property (nonatomic,copy) NSString * mimeType;

@end

在這里以上的代碼是重要的晨川,基本上對我們要使用的AFNetworking里面的內容的封裝了。大家需要好好理解一下代碼删豺,我也都一一注釋了共虑。

那么這樣的封裝就能滿足我們的實際使用需求嗎?明顯是不行的呀页。雖然我們的使用方便了妈拌,但是在實際使用的時候,比如一個Controller蓬蝶,我們需要請求網絡圖片數據尘分,那么我們就需要在里面寫我們的網絡請求,寫json解析丸氛,寫UI使用培愁。omg,多長多亂呀缓窜。這里的網絡處理根本就不應該出現(xiàn)在Controller里面定续,這樣的設計是累贅的,高內聚的雹洗,不符合我們程序的設計理念。

所以我們來寫寫實際需求的代碼卧波,現(xiàn)在假設我們要從網絡上獲取一個json时肿,里面包含一個數組的字符串。我們如何來實現(xiàn):

首先我們需要用到一個model轉化庫Mantle港粱,同樣的方法導入螃成。然后我們來定義我們接收的model:   CHListObject.h/.m
@interface CHListObject : MTLModel <MTLJSONSerializing>

@property (nonatomic, assign) NSInteger ID;
@property (nonatomic, strong) NSString *name;

@end
#import "CHListObject.h"

@implementation CHListObject

+(NSDictionary *)JSONKeyPathsByPropertyKey
{
    return @{
             @"ID":@"id",
             @"name":@"name",
             };
}

@end
我們將在我們的實際獲取代碼里面把json數據通過這個第三方庫轉換過來旦签,這是十分方便的。大家同樣需要去學一下Mantle的使用方法寸宏。(ps:是不是覺得要學很多東西宁炫,不要氣餒)

接下來是我們的獲取文件類CHServiceNetRequest.h/.m
#import <Foundation/Foundation.h>
#import "CHListObject.h"

typedef void(^Failure) (NSError* error);

@interface CHServiceNetRequest : NSObject

+(CHServiceNetRequest*)Instance;

/**
 *    獲取列表信息
 *
 *    @param  token
 *    @param  success
 *    @param  failure
 */

+(void)getListWithToken:(NSString*)token
                success:(void(^)(NSArray<CHListObject*> *list))success
                failure:(Failure)failure;

@end
#import "CHServiceNetRequest.h"
#import "CHHttpRequest.h"

@implementation CHServiceNetRequest

//單例模式
+(CHServiceNetRequest*)Instance
{
    static dispatch_once_t once_token;
    static CHServiceNetRequest* service = nil;
    if (service == nil) {
        dispatch_once(&once_token,^{
            service = [[CHServiceNetRequest alloc]init];
        });
    }
    return service;
}

//需求下的網絡請求,返回CHListObject的數組
+(void)getListWithToken:(NSString *)token success:(void (^)(NSArray<CHListObject *> *))success failure:(Failure)failure
{
    NSMutableDictionary *dic = [NSMutableDictionary dictionary];
    [dic setObject:token forKey:@"token"];
    //==token是什么東西氮凝,大家需要自己去了解一下==
    
    [CHHttpRequest postWithURLString:@"這里寫入一個后臺地址" parameters:dic success:^(id responerObject) {
        //請求成功
        //如果和后臺溝通正確羔巢,這里的responerObject應該是一個json
        //下面開始使用Mantle來處理獲取的json
        NSArray* data = (NSArray*)responerObject;
        //由于我們假設json里面是一個數組,所以我們用一個listArr來接收我們的網絡數據
        NSMutableArray* listArr = [NSMutableArray array];
        //取出數據
        for (NSDictionary *dic in data) {
            CHListObject *obj = [MTLJSONAdapter modelOfClass:[CHListObject class] fromJSONDictionary:dic error:nil];
            [listArr addObject:obj];
        }
        //success輸出
        if (success) {
            success([listArr copy]);
        }
        
    } failure:^(NSError *error) {
        //請求失敗
        failure(error);
    }];
}

@end

先在這里告訴大家罩阵,這樣已經ok了竿秆!實際使用時只需要使用CHServiceNetRequest里面的方法就行,具體在那個Controller里使用稿壁,直接返回我們json解析出來的listArr數據幽钢,Controller里面完全摒棄冗長的代碼量。

相信大家可能會跳著看以上的代碼傅是,可能也是感覺太長了匪燕,難以理解,所以有點放棄了喧笔。這里也不多說帽驯,相信大家還是能找到適合自己學習的方法的。bye溃斋!

聯(lián)系方式:401518215@qq.com

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末界拦,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子梗劫,更是在濱河造成了極大的恐慌享甸,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件梳侨,死亡現(xiàn)場離奇詭異蛉威,居然都是意外死亡,警方通過查閱死者的電腦和手機走哺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門蚯嫌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人丙躏,你說我怎么就攤上這事择示。” “怎么了晒旅?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵栅盲,是天一觀的道長。 經常有香客問我废恋,道長谈秫,這世上最難降的妖魔是什么扒寄? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮拟烫,結果婚禮上该编,老公的妹妹穿的比我還像新娘。我一直安慰自己硕淑,他們只是感情好课竣,可當我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著喜颁,像睡著了一般稠氮。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上半开,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天隔披,我揣著相機與錄音,去河邊找鬼寂拆。 笑死奢米,一個胖子當著我的面吹牛,可吹牛的內容都是我干的纠永。 我是一名探鬼主播鬓长,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼尝江!你這毒婦竟也來了涉波?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤炭序,失蹤者是張志新(化名)和其女友劉穎啤覆,沒想到半個月后,有當地人在樹林里發(fā)現(xiàn)了一具尸體惭聂,經...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡窗声,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了辜纲。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片笨觅。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖耕腾,靈堂內的尸體忽然破棺而出见剩,到底是詐尸還是另有隱情,我是刑警寧澤扫俺,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布苍苞,位于F島的核電站,受9級特大地震影響牵舵,放射性物質發(fā)生泄漏柒啤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一畸颅、第九天 我趴在偏房一處隱蔽的房頂上張望担巩。 院中可真熱鬧,春花似錦没炒、人聲如沸涛癌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽拳话。三九已至,卻和暖如春种吸,著一層夾襖步出監(jiān)牢的瞬間弃衍,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工坚俗, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留镜盯,地道東北人。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓猖败,卻偏偏與公主長得像速缆,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子恩闻,可洞房花燭夜當晚...
    茶點故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,515評論 25 707
  • 發(fā)現(xiàn) 關注 消息 iOS 第三方庫艺糜、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,029評論 4 62
  • 我從小就有一些拖延的毛病幢尚,做事情了經常三分鐘熱度破停,這些生活中的壞習慣直到工作后也無法徹底改變,目前傳統(tǒng)行業(yè)創(chuàng)...
    archei閱讀 381評論 2 1
  • 關于寫作最初從QQ留言板開始,跌宕起伏的情緒边涕,唯有記錄下來才能得到最好的發(fā)泄晤碘,不會去計較格式、符號功蜓、語法 ...
    初人未勒閱讀 237評論 0 1
  • 實在慚愧霸耙! 在小學的時候式撼,我就有讀過這句“吾生也有涯童社,而知也無涯。以有涯隨無涯著隆,怠已扰楼;已而為知者呀癣,怠而已矣”,前...
    唯道集虛閱讀 471評論 0 1