JC专题iOSiOS开发文集

JSONModel和AFNetworking结合的轻量级网络请求

2016-06-30  本文已影响760人  feae4ff3b06a

网络请求一直以来都是移动开发的必备,封装一个简单又好用的网络框架也是不易之事。这篇文章也是我推荐的重点,如何以对象的方式发送网络请求和返回响应数据,来看看 JSONModelAFNetworking 是怎么结合完成这些操作的。

这套框架目前支持以下操作:

  1. 普通的 GET、POST网络请求。
  2. 文件或数据上传。

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,有任何疑问或者建议请在下方留言。

上一篇下一篇

猜你喜欢

热点阅读