菜鳥用RAC基于AFNetworking 3.0網(wǎng)絡(luò)的封裝搭建記錄(四)

前言

這幾天自己在學(xué)習(xí)RAC,學(xué)習(xí)了幾天對RAC有了一定基礎(chǔ)了解词爬,如之前寫的
菜鳥開始學(xué)習(xí)ReactiveObjc運(yùn)用的記錄(二)
菜鳥運(yùn)用RAC對replay,replayLast,replayLazily記錄(三)
看著前面寫的,雖然是基礎(chǔ)率挣,但自己堅(jiān)持記錄下來枢里,心里還是有滿滿的成就感的,哈哈~
好,回到我今天學(xué)到的東西淳蔼。在學(xué)習(xí)RAC的幾天,心里就想著怎么把RAC用到自己的工程中裁眯,因?yàn)閷?shí)踐后才是自己的東西肖方! gitHub代碼地址:https://github.com/CgtST/ReactiveObjCDemo.git

怎么開始封裝呢

自己以前的工程是用的AFNetWorking網(wǎng)絡(luò)庫,一般是寫個(gè)單例對AFNetWorking的二次封裝未状。但如果用萬物皆信號的RAC又怎么處理俯画,其實(shí)在心里琢磨了很久。網(wǎng)上有用RAC中的 command來表示請求來執(zhí)行的過程的司草,有用的以前的網(wǎng)絡(luò)類中直接改成Singnal方式的艰垂。 這里我用RACSignal replayzily 來處理泡仗。于是用xcode新建工程,邊寫邊思考來寫猜憎。
心里琢磨著建立幾個(gè)類呢娩怎?建立了一個(gè)請求之前的處理類,請求執(zhí)行類胰柑,數(shù)據(jù)返回處理類,后面還有個(gè)寫base url等宏的文件

屏幕快照 2019-03-29 下午6.31.19.png

這幾個(gè)文件的打算功能

  • PAHttpRequest: 處理網(wǎng)絡(luò)請求參數(shù)類型截亦,如每個(gè)請求有固定的參數(shù)(app 版本號,客戶端ios等)柬讨,處理base url與path路徑的拼接崩瓤,以及請求參數(shù)的加密等內(nèi)容,解析成指定類的參數(shù)踩官;
  • PAHTTPService:對AF的二次封裝處理Get却桶,Post,文件上傳等功能了。
  • PAHTTPResponse:解析成指定的數(shù)據(jù)模型蔗牡,返回?cái)?shù)據(jù)的處理颖系,錯(cuò)誤處理等

請求參數(shù)類PAHttpRequest

在PAHttpRequest.h中如下,自己只定義了一個(gè)方法想到時(shí)返回指定的數(shù)據(jù)model類辩越。

typedef NS_ENUM(NSUInteger , PARequestType)
{
    PARequestTypePost = 0, //Post請求
    PAHttpRequestGet,
};

@interface PAHttpRequest : NSObject

@property (nonatomic,copy) NSString * path; //就基于baseUrl的相對path
@property (nonatomic) PARequestType requestType;  //P(這里沒用到了)
@property (nonatomic,strong) NSDictionary * params; //參數(shù)
@property (nonatomic,strong) Class resultClass; //返回指定的類結(jié)構(gòu)

/**
 請求類
 
 @param path 相對于basePath的path
 @param dict 參數(shù)字典集
 @param resultClass 返回指定的類型
 */
+(instancetype)requestWithPath:(NSString *)path params:(NSDictionary *)dict convertResultClass:(nullable Class)resultClass;

主要那個(gè)方法的如下嘁扼,當(dāng)然到時(shí)可以添加請求參數(shù)簽名,固定請求參數(shù)等在這個(gè)類里黔攒。

/*功能
 1.這個(gè)類可以添加常用的默認(rèn)請求參數(shù):如token,app版本號等的處理
 2.處理請求數(shù)據(jù)的加密等
 */

/**
 請求類
 
 @param path 相對于basePath的path
 @param dict 參數(shù)字典集
 @param resultClass 返回指定的類型
 */
+(instancetype)requestWithPath:(NSString *)path params:(NSDictionary *)dict convertResultClass:(nullable Class)resultClass
{
  return  [[self alloc] initReqestParamsWithPath:path params:dict convertResultClass:resultClass];
}


-(instancetype)initReqestParamsWithPath:(NSString *)path params:(NSDictionary *)params convertResultClass:(Class)resultClass
{
    self = [super init];
    if (self) {
   
        self.path = [NSString stringWithFormat:@"%@%@",BaseHttpUrl, path];  //拼接完整的url
        self.params = params;
        self.resultClass = resultClass;
    }
    
    return self;
    
}

請求執(zhí)行類PAHTTPService

這里主要是一個(gè)單例偷拔,及請求的寫法。在.h中亏钩,

#import <Foundation/Foundation.h>
#import <ReactiveObjC/ReactiveObjC.h>
#import "PAHttpRequest.h"

NS_ASSUME_NONNULL_BEGIN

@interface PAHTTPService :NSObject

+(instancetype)shareInstance;

//Post
-(RACSignal *)getRequestNetWorkData:(PAHttpRequest *)request;

//Get請求方法
-(RACSignal *)postRequestNetWorkData:(PAHttpRequest *)request;

-(instancetype)init   NS_UNAVAILABLE;
+(instancetype)new  NS_UNAVAILABLE;
-(id)copy NS_UNAVAILABLE;
-(id)mutableCopy NS_UNAVAILABLE;

@end

NS_ASSUME_NONNULL_END

.m中:

#import "PAHTTPService.h"
#import "PAHttpConfigs.h"
#import <AFNetworking/AFNetworking.h>
#import "PAHttpResponse.h"


NSString * const PAHttpErrorDomain = @"PAHTTPErrorDomain";
NSString * const PAHttpErrorMessage = @"PAHTTPErroMassage";

@interface PAHTTPService ()
@property (nonatomic,strong) AFHTTPSessionManager * netManager;
@end

@implementation PAHTTPService

+(instancetype)shareInstance
{
    static PAHTTPService * service = nil;
    dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        service = [[self alloc] init];
        
    });
    return service;
    
}

-(void)configHttpService
{
    
    self.netManager.requestSerializer.timeoutInterval = 10.f;
    self.netManager.responseSerializer.acceptableContentTypes =  [NSSet setWithObjects:@"application/json",
                                                       @"text/json",
                                                       @"text/javascript",
                                                       @"text/html",
                                                       @"text/plain",
                                                       @"text/html",
                                                       nil];
    self.netManager.requestSerializer.stringEncoding = NSUTF8StringEncoding;
    
   /*
    設(shè)置請求頭的設(shè)置
    //
    [self.netManager.requestSerializer setValue:TOKEN forHTTPHeaderField:@"token-id"];
    
    */
    
   //// 安全策略
    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy defaultPolicy];
    //allowInvalidCertificates 是否允許無效證書(也就是自建的證書)莲绰,默認(rèn)為NO
    //如果是需要驗(yàn)證自建證書,需要設(shè)置為YES
    securityPolicy.allowInvalidCertificates = YES;
    //validatesDomainName 是否需要驗(yàn)證域名姑丑,默認(rèn)為YES蛤签;
    //假如證書的域名與你請求的域名不一致,需把該項(xiàng)設(shè)置為NO
    //主要用于這種情況:客戶端請求的是子域名栅哀,而證書上的是另外一個(gè)域名震肮。因?yàn)镾SL證書上的域名是獨(dú)立的,假如證書上注冊的域名是www.google.com留拾,那么mail.google.com是無法驗(yàn)證通過的戳晌;當(dāng)然,有錢可以注冊通配符的域名*.google.com痴柔,但這個(gè)還是比較貴的沦偎。
    securityPolicy.validatesDomainName = NO;
    
    self.netManager.securityPolicy = securityPolicy;
    
    /*
      添加網(wǎng)絡(luò)監(jiān)測等
     //
     [[AFNetworkReachabilityManager sharedManager] startMonitoring];
     [self.netManager.reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
     if (status == AFNetworkReachabilityStatusUnknown) {
     //未知網(wǎng)絡(luò)
     
     }else if(status == AFNetworkReachabilityStatusNotReachable){
     //未連接
     }else{
     //有網(wǎng)絡(luò)
     }
     }];
     
     */
    
}

-(RACSignal *)postRequestNetWorkData:(PAHttpRequest *)request
{
    if (!request) {
        return  [RACSignal  error:[NSError errorWithDomain:PAHttpErrorDomain code:-1 userInfo:nil]];
    }
    
    
    RACSignal * signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        
        //創(chuàng)建網(wǎng)絡(luò)請求
        NSLog(@"======== %@ %@",request.path,request.params);
        __block  NSURLSessionDataTask * task = nil;
        task = [self.netManager POST:request.path parameters:request.params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            
            PAHttpResponse * response = [[PAHttpResponse alloc] initWithResponseSuccess:responseObject code:0 resultClass:nil];
            NSLog(@"*******data : %@",response.responseObject);
            [subscriber sendNext:response.responseObject];
            [subscriber sendCompleted];
            
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
              NSLog(@"報(bào)錯(cuò)了%@",error);
            [subscriber sendError:error];
        }];
        
        return [RACDisposable disposableWithBlock:^{
            [task cancel];  //取消
        }];
    }];
    
    return [signal replayLazily];  //多次訂閱同樣的信號,執(zhí)行一次。
}


#pragma mark - Lazily

-(AFHTTPSessionManager *)netManager
{
    if (_netManager == nil) {
        _netManager = [AFHTTPSessionManager manager];
        [self configHttpService];
    }
    return _netManager;
}


@end

請求數(shù)據(jù)處理類PAHttpResponse

這類負(fù)責(zé)數(shù)據(jù)解析豪嚎,響應(yīng)錯(cuò)誤的處理等搔驼。主要看各自的業(yè)務(wù),這里只是粗略的寫了一下侈询。打算定義2個(gè)方法舌涨,一個(gè)成功輸出的數(shù)據(jù)接口,一個(gè)失敗輸出的扔字。在定義的屬性時(shí)囊嘉,只讀。打算數(shù)據(jù)解析用MJExtension革为。

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface PAHttpResponse : NSObject

@property(nonatomic,assign,readonly) BOOL isSuccess;  //請求成功的判斷
@property (nonatomic,assign,readonly) NSInteger code; //返回成功或失敗的code
@property (nonatomic,copy,readonly) NSString * message; //返回的信息

@property (nonatomic,strong,readonly) id  responseObject; //原裝的返回
@property (nonatomic,strong,readonly) id  jsonClassObject; //解析成指定class的返回

@property (nonatomic,strong,readonly) NSError *  resError; //可能服務(wù)器返回的錯(cuò)誤信息

-(instancetype)initWithResponseSuccess:(id) result code:(NSInteger )code resultClass:(nullable Class)resultClass;

-(instancetype)initWithResponseError:(NSError *) err code:(NSInteger )code;

@end

NS_ASSUME_NONNULL_END

/* 功能
  1. 對返回的數(shù)據(jù)的處理扭粱,如輸出成指定的model
  2.處理返回的邏輯,如錯(cuò)誤信息
 */

#import "PAHttpResponse.h"
@interface PAHttpResponse ()

@property(nonatomic,assign,readwrite) BOOL isSuccess;  //請求成功的判斷
@property (nonatomic,assign,readwrite) NSInteger code; //返回成功或失敗的code
@property (nonatomic,copy,readwrite) NSString * message; //返回的信息

@property (nonatomic,strong,readwrite) id  responseObject; //原裝的返回
@property (nonatomic,strong,readwrite) id  jsonClassObject; //解析成指定class的返回
@property (nonatomic,strong,readwrite) NSError *  resError; //可能服務(wù)器返回的錯(cuò)誤信息

@end

@implementation PAHttpResponse

-(instancetype)initWithResponseSuccess:(id) result code:(NSInteger )code resultClass:(nullable Class)resultClass
{
    if (self = [super init]) {
        self.isSuccess = YES; //這里看自己工程篷角,有些要code == 0才算成功
        self.responseObject = result;
        self.code = code;
        
        if (resultClass) {  //如果要 解析成指定的類型
            /*
            //用MJExtension來解析
            id convertClass = nil;
            if ([result isKindOfClass:[NSArray class]]) {
                NSMutableArray *resultList = [NSMutableArray array];
                
                for (id dataItem in result) {
                    [resultList addObject:[resultClass mj_objectWithKeyValues:dataItem]];
                }
                
                convertClass = resultList;
            } else if ([result isKindOfClass:[NSNumber class]] || [data isKindOfClass:[NSString class]]) {
                convertClass = result;
            } else if ([result isSubclassOfClass:[NSDictionary class]]) {
                convertClass = resultClassData;
            } else {
                
                convertClass = [resultClass mj_objectWithKeyValues:result];
            }
            self.jsonClassObject = convertClass;
            */
        }
    }
    return self;
}


-(instancetype)initWithResponseError:(NSError *) err code:(NSInteger )code
{
    if (self = [super init]) {
        self.isSuccess = NO;
        self.resError = err;
        self.code = code;
        
        //從error里拿message
//        self.message = message;
    }
    return self;
}


@end

請求常用宏的定義PAHttpConfigs

用來放一些url 配置等

1B584671-0987-48C3-891F-0F892DF7246D.png

自己心里面大概就是這么想的焊刹,只是寫了一下大概架子系任,具體的豐富功能加上去不是很難恳蹲,這就是今天學(xué)得內(nèi)容

最后調(diào)用

簡單的調(diào)用如下,是可以正確拿到數(shù)據(jù)的俩滥,嘻嘻~嘉蕾,搞定。

屏幕快照 2019-03-29 下午6.41.33.png

后續(xù):
過了幾天來看寫的請求發(fā)現(xiàn)封裝的還不夠好霜旧,于是自己添加了個(gè)請求的工廠類方法:
請求工廠方法.png

.h方法

/*
 工廠模式寫全部的網(wǎng)絡(luò)請求
 
 */


#import <Foundation/Foundation.h>
#import <ReactiveObjC/ReactiveObjC.h>

NS_ASSUME_NONNULL_BEGIN

@interface PANetTools : NSObject

+(RACSignal *)requestHotRoom;


@end

NS_ASSUME_NONNULL_END

.m

#import "PANetTools.h"
#import "PAHttpRequest.h"
#import <ReactiveObjC/ReactiveObjC.h>
#import "PAHttpConfigs.h"
#import "PAHTTPService.h"


@implementation PANetTools

+(RACSignal *)requestHotRoom
{
    NSMutableDictionary * paras = [NSMutableDictionary dictionary];
    PAHttpRequest * request = [PAHttpRequest requestWithPath:HotLivePath params:paras convertResultClass:nil];
    return  [[PAHTTPService shareInstance]postRequestNetWorkData:request];
}


@end

最后調(diào)用請求方法如下:使用更加簡單错忱,嘻嘻~

  [[twoBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
        @strongify(self);
        [[PANetTools requestHotRoom] subscribeNext:^(id  _Nullable x) {
            NSLog(@"=======數(shù)據(jù):%@",x);
        }error:^(NSError * _Nullable error) {
            NSLog(@"=======s失敗:%@",error);
        }];
        
    }];

總結(jié)

  • 在學(xué)RAC的過程中挂据,網(wǎng)絡(luò)的封裝基本就可以了以清。感覺比較深的是怎么用信號來寫。網(wǎng)上看好多文章不如自己邊摸索邊寫崎逃。
  • 后期打算用RAC 寫MVVM在工程中的運(yùn)用掷倔。加油!
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末个绍,一起剝皮案震驚了整個(gè)濱河市勒葱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌巴柿,老刑警劉巖凛虽,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異广恢,居然都是意外死亡凯旋,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瓦阐,“玉大人蜗侈,你說我怎么就攤上這事∷” “怎么了踏幻?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長戳杀。 經(jīng)常有香客問我该面,道長,這世上最難降的妖魔是什么信卡? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任隔缀,我火速辦了婚禮,結(jié)果婚禮上傍菇,老公的妹妹穿的比我還像新娘猾瘸。我一直安慰自己,他們只是感情好丢习,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布牵触。 她就那樣靜靜地躺著,像睡著了一般咐低。 火紅的嫁衣襯著肌膚如雪揽思。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天见擦,我揣著相機(jī)與錄音钉汗,去河邊找鬼。 笑死鲤屡,一個(gè)胖子當(dāng)著我的面吹牛损痰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播酒来,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼卢未,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了役首?” 一聲冷哼從身側(cè)響起尝丐,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎衡奥,沒想到半個(gè)月后爹袁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡矮固,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年失息,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了譬淳。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,424評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡盹兢,死狀恐怖邻梆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情绎秒,我是刑警寧澤浦妄,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站见芹,受9級特大地震影響剂娄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜玄呛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一阅懦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧徘铝,春花似錦耳胎、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至怠缸,卻和暖如春诗轻,著一層夾襖步出監(jiān)牢的瞬間钳宪,已是汗流浹背揭北。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留吏颖,地道東北人搔体。 一個(gè)月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像半醉,于是被迫代替她去往敵國和親疚俱。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫缩多、插件呆奕、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,117評論 4 61
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,109評論 1 32
  • 國家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說閱讀 11,002評論 6 13
  • iOS網(wǎng)絡(luò)架構(gòu)討論梳理整理中。衬吆。梁钾。 其實(shí)如果沒有APIManager這一層是沒法使用delegate的,畢竟多個(gè)單...
    yhtang閱讀 5,206評論 1 23
  • 悶熱潮濕會讓人心煩意亂逊抡,靜下心來的時(shí)候又開始無窮懷念姆泻。 喝點(diǎn)小酒,在安適的空調(diào)溫度下不覺睡去,夢中回到故鄉(xiāng)拇勃,回到兒...
    烈酒長歌閱讀 392評論 2 2