封装项目网络库

封装一个网络库的一些思路(基于YTKNetwork)

为什么要封装网络库

大家都知晓网络层是一个项目的灵魂,所以网络层写的是否规范、是否简洁、是否完整关系到一个项目的整体质量,甚至于项目的性能。因此在这里我给大家分享下我是如何封装一个项目所用的网络库的(其实就是把整个项目所用的接口,写成一个库,方便项目使用)。

封装网络库的作用

1.请求数据
2.对每个接口都可以进行缓存时间设置
3.利用MJExtension进行字典模型转换
4.更加灵活方便的调用各个接口,降低了耦合性

如何封装

这里我列举一个用户登录的请求
首先基于YTKRequest封装一个SuperRequest类
@interface SuperRequestAPI : YTKRequest

@property (nonatomic, strong, readonly) YSNetworkConfig *config;

- (NSMutableDictionary *)signAndEncode:(NSMutableDictionary *)param;

- (void)printRequestInfo;

@end

@implementation SuperRequestAPI

- (NSMutableDictionary *)signAndEncode:(NSMutableDictionary *)params {
    NSMutableArray *paramArray = [[NSMutableArray alloc] init];
    
    NSArray *sortArray = [[params allKeys] sortedArrayUsingSelector:@selector(compare:)];
    
    for (NSString *key in sortArray) {
        NSString *param = [NSString stringWithFormat:@"%@", [params objectForKey:key]];
        if (param && ![param isEqualToString:@""]) {
            [paramArray addObject:param];
        }
    }
    
    // 获取加密字符串
    NSString *encode = [YSSecurityHelper getEncodePostMsgDataWithParams:paramArray encodeKey:self.config.encodeKey];
    
    // 将加密字符串作为参数上传
    [params setObject:encode forKey:@"sign"];
    return params;
}

#pragma mark - 配置信息
- (YTKRequestMethod)requestMethod {
    return YTKRequestMethodPost;
}

- (NSString *)baseUrl {
    return self.config.serviceURL;
}


- (NSTimeInterval)requestTimeoutInterval {
    return 30;
}

- (NSInteger)cacheTimeInSeconds {
    return kCacheTime;
}

- (void)printRequestInfo {
    NSMutableString *requestString = [[NSMutableString alloc] init];
    [requestString appendString:self.baseUrl];
    [requestString appendString:self.requestUrl];
    
    NSArray *sortArray = [[self.requestArgument allKeys] sortedArrayUsingSelector:@selector(compare:)];
    
    for (NSString *key in sortArray) {
        [requestString appendString:@"&"];
        [requestString appendString:key];
        [requestString appendString:@"="];
        [requestString appendString:self.requestArgument[key]];   
    }
    
    NSLog(@"请求地址:==========%@", requestString);
}

这个类可以对请求参数进行签名和加密、设置缓存时间、打印请求地址等等一些操作。

创建一个LoginRequestAPI类继承SuperRequestAPI
#import "SuperRequestAPI.h"

@interface LoginRequestAPI : SuperRequestAPI

/**
 *  @brief  登录请求参数
 *
 *  @param userName 用户名
 *  @param password 密码
 *
 *  @return LoginRequestModel
 */
- (id)initWithUserName:(NSString *)userName password:(NSString *)password;
@end



#import "LoginRequestAPI.h"

@interface LoginRequestAPI ()

@property (nonatomic, strong) NSString *userName;
@property (nonatomic, strong) NSString *password;
// 设置请求参数
@property (nonatomic, strong) NSMutableDictionary *requestParam;

@end

@implementation LoginRequestAPI

- (id)initWithUserName:(NSString *)userName password:(NSString *)password {
    
    if (self = [super init]) {
        _userName  = userName;
        _password = password;
    }
    return self;
}

#pragma mark - Getter && Setter
- (NSMutableDictionary *)requestParam {
    if (_requestParam == nil) {
        
        /** 赋值参数字段 */
        _requestParam = [[NSMutableDictionary alloc] init];
       
        [_requestParam setObject:(_userName ? _userName : @"") forKey:@"userName"];
        [_requestParam setObject:(_password ? _password : @"") forKey:@"password"];
        
        //对参数进行签名和加密处理
        _requestParam = [self signAndEncode:_requestParam];
    }
    return _requestParam;
}

#pragma mark - 配置请求信息

- (id)requestArgument {
    return self.requestParam;
}

@end

在这个请求参数类里面你可以设置你的请求路径,版本号、请求参数等等。完整的封装了请求参数,需要的话可以对参数进行签名和加密处理。

创建相应的模型类

这里我们用到MJExtension进行字典模型转换,对字段进行了一一映射处理,MJExtension具体用法请参考https://github.com/CoderMJLee/MJExtension

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

@interface LoginDetail : NSObject

@property (nonatomic, strong) NSString *mAuthCode;
@property (nonatomic, strong) NSString *mAvatar;
@property (nonatomic, strong) NSString *mCae;
@property (nonatomic, strong) NSString *mId;
@property (nonatomic, strong) NSString *mIsThird;
@property (nonatomic, strong) NSString *mLastLoginTime;
@property (nonatomic, strong) NSString *mPassId;
@property (nonatomic, strong) NSString *mToken;
@property (nonatomic, strong) NSString *mUsername;
@property (nonatomic, strong) NSString *mValidate;

@end

#import "LoginDetail.h"

@implementation PhoneLoginDetail

+ (NSDictionary *)replacedKeyFromPropertyName {
    return @{
             @"mAuthCode" : @"auth_code",
             @"mAvatar" : @"avatar",
             @"mCae" : @"cae",
             @"mId" : @"id",
             @"mIsThird" : @"is_third",
             @"mLastLoginTime" : @"last_login_time",
             @"mPassId" : @"passid",
             @"mToken" : @"token",
             @"mUsername" : @"username",
             @"mValidate" : @"validate"
             };
}
@end

最后一步,就是写请求接口类了

这个类里面可以把所有的请求接口写进去,最好用类方法。

@interface YBNetwork : NSObject
+ (void)requestLoginDetailWithUserName:(NSString *)userName
                                   password:(NSString *)password
                                    success:(void (^)(LoginDetail * LoginDetail, BOOL success, NSDictionary *responseObject))successBlock
                                    failure:(void (^)(NSDictionary *requestParam))failureBlock;
@end


@implementation YBNetwork

/*!
 *  请求用户登录信息
 *  @param userName    用户名
 *  @param password    密码
 *  @param successBlock 成功block
 *  @param failureBlock 失败block
 */
+ (void)requestLoginDetailWithUserName:(NSString *)userName
                                   password:(NSString *)password
                                    success:(void (^)(LoginDetail * LoginDetail, BOOL success, NSDictionary *responseObject))successBlock
                                    failure:(void (^)(NSDictionary *requestParam))failureBlock {
    
    [YBNetwork addAcceptableContentTypes];
    
    LoginRequestAPI *api = [[LoginRequestAPI alloc] initWithUserName:userName password:password];;
    
    [api startWithCompletionBlockWithSuccess:^(__kindof YTKBaseRequest *request) {
        NSDictionary *responseDictionary = [request responseJSONObject];
        NSString *status;
        if (DATA_STRING(responseDictionary[@"status"])) status = responseDictionary[@"status"];
        if (200 == status.integerValue) {
            if (DATA_DICTIONARY(responseDictionary[@"info"])) {
                NSDictionary *info = responseDictionary[@"info"];
                LoginDetail *phoneLoginDetail = [LoginDetail mj_objectWithKeyValues:info];
                // 请求成功
                successBlock(phoneLoginDetail, YES, responseDictionary);
            } else {
                // 返回数据格式存在问题
                successBlock(nil, YES, responseDictionary);
            }
        } else {
            // 返回的status非法
            successBlock(nil, NO, responseDictionary);
        }
    } failure:^(__kindof YTKBaseRequest *request) {
        // 网络请求失败
        failureBlock(request.requestArgument);
    }];
    [api printRequestInfo];
}

这里我的一个思路是基于YTKNetwork写这个接口,采用block回调形式,回调两个参数,一个是success和failure,success返回模型实例对象,success布尔值以及返回json转换后的字典,之所以还返回字典是便于项目中调试接口用。failure返回的就是失败的字典喽!
整个封装大概就是这个思路,我这里纯粹是抛砖引玉,提供一个参考的封装方法,大家可以多多交流!收工!!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,376评论 25 707
  • AFHTTPRequestOperationManager 网络传输协议UDP、TCP、Http、Socket、X...
    Carden阅读 4,315评论 0 12
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,016评论 4 62
  • 忙完下班 青儿说今天过节一起吃顿饭 点了她最喜欢的三杯鸡 与广东一带不同 湖南的冬至并不是个很特别很隆重的日子
    aijer09阅读 140评论 0 0
  • 看到这个题目的时候,嗯,我什么情况下会失控呢? 在没有自控力的时候,我就失控了。 很多情况下,在你没有自控力的的时...
    笑莉说阅读 243评论 4 1