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) {
    
}];
  1. 后台需要什么参数,只管在MSModel.h中添加属性即可,不必关心MSModel.m的实现
  2. (如果觉得string_、integer_、float_这三个前缀碍眼,也可以去掉,只不过需要传进来的参数全部为NSString类型,传的时候需要稍微转换一下)
上一篇下一篇

猜你喜欢

热点阅读