iOS封装AFN的Para参数(仿Masonry)
2019-04-25 本文已影响0人
_moses
一般我们封装AFN,大多都是这个样子
@interface MSNetwork : AFHTTPSessionManager
+ (void)POST:(NSString *)url
para:(NSDictionary *)para
success:(void (^)(NSDictionary *dict))success
failure:(void (^)(NSError *error))failure;
@end
@implementation MSNetwork
+ (void)POST:(NSString *)url
para:(NSDictionary *)para
success:(void (^)(NSDictionary *dict))success
failure:(void (^)(NSError *error))failure {
MSNetwork *network = [MSNetwork new];
network.requestSerializer = [AFHTTPRequestSerializer serializer];
network.responseSerializer = [AFJSONResponseSerializer serializer];
[network.requestSerializer willChangeValueForKey:@"timeoutInterval"];
network.requestSerializer.timeoutInterval = 10;
[network.requestSerializer didChangeValueForKey:@"timeoutInterval"];
[network POST:url parameters:para progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
if (success) {
success(responseObject);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
if (failure) {
failure(error);
}
}];
}
@end
控制器调用的时候这样写
// 后台需要的参数为name、age、sex、score
[MSNetwork POST:@"login" para:@{@"name":@"moses",@"age":@18,@"sex":@"男",@"score"@6.66} success:^(NSDictionary *dict) {
} failure:^(NSError *error) {
}];
用多了Masonry就总会闪现一些奇思妙想:用Masonry的链式编程方式将参数字典para传给AFN
@interface MSNetwork : AFHTTPSessionManager
+ (void)POST:(NSString *)url
para:(void (^)(MSModel *model))para
success:(void (^)(NSDictionary *dict))success
failure:(void (^)(NSError *error))failure;
@end
@implementation MSNetwork
+ (void)POST:(NSString *)url
para:(void (^)(MSModel *model))para
success:(void (^)(NSDictionary *dict))success
failure:(void (^)(NSError *error))failure {
NSMutableDictionary *dict;
if (para) {
MSModel *model = [MSModel new];
para(model);
dict = [model valueForKey:@"_paraDict"];
}
NSLog(@"%@", dict);
MSNetwork *network = [MSNetwork new];
network.requestSerializer = [AFHTTPRequestSerializer serializer];
network.responseSerializer = [AFJSONResponseSerializer serializer];
[network.requestSerializer willChangeValueForKey:@"timeoutInterval"];
network.requestSerializer.timeoutInterval = 10;
[network.requestSerializer didChangeValueForKey:@"timeoutInterval"];
[network POST:url parameters:dict progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
if (success) {
success(responseObject);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
if (failure) {
failure(error);
}
}];
}
@end
@interface MSModel : NSObject
@property(nonatomic,copy,readonly) MSModel *(^string_name)(NSString *name);
@property(nonatomic,copy,readonly) MSModel *(^integer_age)(NSInteger age);
@property(nonatomic,copy,readonly) MSModel *(^float_score)(CGFloat score);
@property(nonatomic,copy,readonly) MSModel *(^string_sex)(NSString *sex);
@end
#import <objc/runtime.h>
@interface MSModel () {
NSMutableDictionary *_paraDict;
}
@end
@implementation MSModel
- (instancetype)init {
if (self = [super init]) {
_paraDict = [NSMutableDictionary dictionary];
}
return self;
}
+ (void)load {
unsigned int propertyCount = 0;
objc_property_t *propertyList = class_copyPropertyList([self class], &propertyCount);
for (unsigned int i = 0; i < propertyCount; i++) {
NSString * propertyName = [NSString stringWithUTF8String:property_getName(propertyList[i])];
if ([propertyName hasPrefix:@"string_"]) {
class_replaceMethod([self class], NSSelectorFromString(propertyName), (IMP)ms_stringMethod, "@@:");
} else if ([propertyName hasPrefix:@"integer_"]) {
class_replaceMethod([self class], NSSelectorFromString(propertyName), (IMP)ms_integerMethod, "@@:");
} else if ([propertyName hasPrefix:@"float_"]) {
class_replaceMethod([self class], NSSelectorFromString(propertyName), (IMP)ms_floatMethod, "@@:");
} else {
NSAssert(0, @"属性名需要按规则命名");
}
}
}
static id ms_stringMethod(id self, SEL _cmd) {
return [self getString:[NSStringFromSelector(_cmd) substringFromIndex:7]];
}
- (MSModel *(^)(NSString *))getString:(NSString *)property {
return ^(NSString *value) {
[_paraDict setValue:value forKey:property];
return self;
};
}
static id ms_integerMethod(id self, SEL _cmd) {
return [self getInteger:[NSStringFromSelector(_cmd) substringFromIndex:8]];
}
- (MSModel *(^)(NSInteger))getInteger:(NSString *)property {
return ^(NSInteger value) {
[_paraDict setValue:@(value) forKey:property];
return self;
};
}
static id ms_floatMethod(id self, SEL _cmd) {
return [self getFloat:[NSStringFromSelector(_cmd) substringFromIndex:6]];
}
- (MSModel *(^)(CGFloat))getFloat:(NSString *)property {
return ^(CGFloat value) {
[_paraDict setValue:@(value) forKey:property];
return self;
};
}
@end
控制器调用的时候这样写
// 后台需要的参数为name、age、sex、score
[MSNetwork POST:@"login" para:^(MSModel *model) {
model.string_name(@"moses").integer_age(18).string_sex(@"男").float_score(6.66);
} success:^(NSDictionary *dict) {
} failure:^(NSError *error) {
}];
- 后台需要什么参数,只管在MSModel.h中添加属性即可,不必关心MSModel.m的实现
- (如果觉得string_、integer_、float_这三个前缀碍眼,也可以去掉,只不过需要传进来的参数全部为NSString类型,传的时候需要稍微转换一下)