背景
在MVC的架构下,我们习惯于在Controller里做很多的逻辑操作,例如发起网络请求并解析返回数据。这么做固然不错,但我个人认为将网络请求抽离出去更好一些,让Controller不去在乎那些细节,也更符合面向对象编程的理念。
现有的AFNetworking
已将网络请求封装的很好,使用起来也很方便。但是还是要在Controller里指定URL、parameters、GET/POST等参数,还要在成功之后解析结果,Controller本不应该关心这些事,Controller应该只是拿到最终的model添加到DataSource里面。因此对AFNetworking做一个简单的封装。
具体实现
//LLBaseRequest.h
typedef NS_ENUM(NSUInteger, LLRequestType) {
LLRequestTypeGet,
LLRequestTypePost,
};
@class LLBaseResponse;
@interface LLBaseRequest : NSObject
@property (nonatomic, copy) NSString *url;
@property (nonatomic, copy) NSDictionary *parameters;
@property (nonatomic, assign) LLRequestType requestType;
+ (instancetype)sharedInstance;
- (instancetype)init NS_UNAVAILABLE;
- (Class)responseClass;
- (void)loadDataSuccess:(nullable void (^)(__kindof LLBaseResponse * _Nullable response))success
failure:(nullable void (^)(NSString * _Nullable errorMessage))failure;
@end
//LLBaseRequest.m
#import <AFNetworking/AFNetworking.h>
@implementation LLBaseRequest
+ (instancetype)sharedInstance {
static LLBaseRequest *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
- (instancetype)init
{
self = [super init];
if (self) {
_url = @"";
_parameters = @{};
_requestType = LLRequestTypeGet;
}
return self;
}
- (Class)responseClass {
return [LLBaseResponse class];
}
- (void)loadDataSuccess:(void (^)(__kindof LLBaseResponse * _Nullable))success failure:(void (^)(NSString * _Nullable))failure {
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
switch ([self requestType]) {
case LLRequestTypeGet:
{
[manager GET:self.url parameters:self.parameters progress:^(NSProgress * _Nonnull downloadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"------response object------\n%@ : %@", [self class], responseObject);
if (success) {
success([[self responseClass] yy_modelWithDictionary:responseObject]);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"------request error------\n%@ : %@", [self class], [error localizedDescription]);
if (failure) {
failure([error localizedDescription]);
}
}];
}
break;
case LLRequestTypePost:
{
[manager POST:self.url parameters:self.parameters progress:^(NSProgress * _Nonnull uploadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"------response object------\n%@ : %@", [self class], responseObject);
if (success) {
success([[self responseClass] yy_modelWithDictionary:responseObject]);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"------request error------\n%@ : %@", [self class], [error localizedDescription]);
if (failure) {
failure([error localizedDescription]);
}
}];
}
break;
default:
break;
}
}
@end
- 采用单例模式
- 子类实现url、parameters、requestType
- 子类指定返回的model
子类继承LLBaseRequest
,实现对应方法
@implementation LLHomeRecommendRequest
- (NSString *)url {
···
}
- (NSDictionary *)parameters {
···
}
- (Class)responseClass {
return [LLHomeRecommendResponse class];
}
- (LLRequestType)requestType {
return LLRequestTypePost;
}
@end
这样在Controller中只用实例化一个request对象,调用一个方法,即可拿到最终的model
LLHomeRecommendRequest *request = [LLHomeRecommendRequest sharedInstance];
__weak typeof(self) weakSelf = self;
[request loadDataSuccess:^(LLHomeRecommendResponse * _Nullable response) {
__strong typeof(weakSelf) strongSelf = weakSelf;
[strongSelf.collectionView.mj_header endRefreshing];
for (LLDiscoverRecommendData *data in response.feedDataGroup.dataList) {
LLBaseComponent *component = [LLBaseComponent componentWithCollectionView:strongSelf.collectionView data:data];
if (component) {
[strongSelf.components addObject:component];
}
}
[strongSelf.collectionView reloadData];
} failure:^(NSString * _Nullable errorMessage) {
__strong typeof(weakSelf) strongSelf = weakSelf;
[strongSelf.collectionView.mj_header endRefreshing];
}];
思考总结
对于从C语言来的同学,应该尽快摆脱之前的编码思维,尽快理解面向对象编程的含义,这样写出来的代码才更易维护,更灵活。
网友评论