JSONModel和AFNetworking结合的轻量级网络请求
2016-06-30 本文已影响760人
feae4ff3b06a
网络请求一直以来都是移动开发的必备,封装一个简单又好用的网络框架也是不易之事。这篇文章也是我推荐的重点,如何以对象的方式发送网络请求和返回响应数据,来看看 JSONModel 和 AFNetworking 是怎么结合完成这些操作的。
这套框架目前支持以下操作:
- 普通的 GET、POST网络请求。
- 文件或数据上传。
GET请求
这里以微信开放平台第三方帐号登录为例子。
/** 响应数据基类 */
@interface JCWeixinBaseResp : JSONModel
@property (nonatomic, copy) NSString<Optional> *errcode;
@property (nonatomic, copy) NSString<Optional> *errmsg;
@end
@implementation JCWeixinBaseResp
@end
/** access token 响应数据信息类 */
@interface JCWeixinAccessTokenResp : JCWeixinBaseResp
@property (nonatomic, copy) NSString<Optional> *access_token;
@property (nonatomic, copy) NSString<Optional> *expires_in;
@property (nonatomic, copy) NSString<Optional> *refresh_token;
@property (nonatomic, copy) NSString<Optional> *openid;
@property (nonatomic, copy) NSString<Optional> *scope;
@end
@implementation JCWeixinAccessTokenResp
@end
/** 微信帐号第三方登录请求基类 */
@interface JCWeixinBaseRequest : JCBaseRequest
@end
@implementation JCWeixinBaseRequest
- (NSString *)baseUrl
{
return @"https://api.weixin.qq.com/";
}
- (void)parseResponseObject:(id)responseObject
error:(NSError *)error
{
// 网络请求超时或服务器错误
if (error) {
if (self.completionBlock) {
self.completionBlock(nil, error);
}
return;
}
// 解析类不存在,直接返回数据
Class decodeClass = [self decodeClass];
if (!decodeClass || ![decodeClass isSubclassOfClass:[JSONModel class]]) {
if (self.completionBlock) {
self.completionBlock(responseObject, nil);
}
return;
}
NSError *respError = nil;
JCWeixinBaseResp *resp = nil;
if ([responseObject isKindOfClass:[NSDictionary class]]) {
resp = [[decodeClass alloc] initWithDictionary:responseObject error:&respError];
} else if ([responseObject isKindOfClass:[NSData class]]) {
resp = [[decodeClass alloc] initWithData:responseObject error:&respError];
} else if ([responseObject isKindOfClass:[NSString class]]) {
resp = [[decodeClass alloc] initWithString:responseObject error:&respError];
}
// 解析数据格式错误
if (respError || !resp) {
if (self.completionBlock) {
self.completionBlock(nil, respError);
}
return;
}
// 业务逻辑错误
if (resp.errcode.integerValue != 0) {
respError = [NSError errorWithDomain:@"network" code:resp.errcode.integerValue userInfo:@{NSLocalizedDescriptionKey: (resp.errmsg ?:@"")}];
if (self.completionBlock) {
self.completionBlock(resp, respError);
}
return;
}
// 正常数据
if (self.completionBlock) {
self.completionBlock(resp, nil);
}
}
@end
/** 通过code获取access_token请求类 */
@interface JCWeixinAccessTokenRequest : JCWeixinBaseRequest
@property (nonatomic, strong) NSString *appid;
@property (nonatomic, strong) NSString *secret;
@property (nonatomic, strong) NSString *code;
@property (nonatomic, strong) NSString *grant_type;
@end
@implementation JCWeixinAccessTokenRequest
- (instancetype)init
{
if (self = [super init]) {
self.grant_type = @"authorization_code";
}
return self;
}
- (NSString *)requestUrl
{
return @"sns/oauth2/access_token";
}
@end
// 发起获取access token的网络请求
self.accessTokenRequest = [[JCWeixinAccessTokenRequest alloc] init];
self.accessTokenRequest.appid = @"your appid";
self.accessTokenRequest.secret = @"your secret";
self.accessTokenRequest.code = @"your code";
[self.accessTokenRequest startRequestWithDecodeClass:[JCWeixinAccessTokenResp class] completion:^(id responseObject, NSError *error) {
// responseObject为JCWeixinAccessTokenResp类对象
}];
文件上传
//JCUploadTestRequest.h
@interface JCUploadTestRequest : JCBaseRequest
@end
//JCUploadTestRequest.m
@implementation JCUploadTestRequest
- (JCRequestMethod)requestMethod
{
return JCRequestMethodPOST;
}
- (NSTimeInterval)requestTimeoutInterval
{
return 10;
}
- (NSString *)baseUrl
{
return @"https://test.baseurl.com";
}
- (NSString *)requestUrl
{
return @"requesturl/testapi";
}
@end
// 发送文件上传请求
- (void)startUploadRequest
{
self.uploadRequest = [[JCUploadTestRequest alloc] init];
[self.uploadRequest setUploadFilePath:@"file path"
uploadName:@"file"];
[self.uploadRequest startRequestWithDecodeClass:[JCUploadTestResp class] progress:^(NSProgress *progress) {
// 通过progress更新进度
} completion:^(id responseObject, NSError *error) {
// responseObject为JCUploadTestResp类对象
}];
}
根据以上的例子,以对象的方式发送网络请求和返回响应数据可以简单概括为:在需要传参数的接口对应的网络请求类中,声明对应参数名称的属性,发送请求的时候给各个属性赋值。请求成功后返回decodeClass对应的实例对象responseObject,可以直接使用该实例对象不用再解析了。
关于框架的更多细节,请关注这里 JCNetworking,有任何疑问或者建议请在下方留言。