基于AFNetworking封裝的網(wǎng)絡(luò)層(一站式解析數(shù)據(jù))

代碼地址: https://github.com/huangxiongbiao12/BGNetworking

1、封裝AFNetworking基本請(qǐng)求方法

封裝原因:當(dāng)AFNetworking的api改變的時(shí)候只需要更改封裝的方法,無(wú)需大面積改動(dòng)代碼(不封裝直接用AFNetworking請(qǐng)求如果AFNetworking的api變化所有用的地方都需要變化)

代碼依賴了MBProgressHUD蒜田,顯示加載圖

封裝思路接口:
1咆瘟、主要封裝了Get Post請(qǐng)求帶HUD和不帶HUD的另外一個(gè)可以選擇是否帶HUD的接口
2浙芙、將上傳圖片的單獨(dú)封裝
3印蔗、封裝了https加載證書驗(yàn)證的方法客冈,只需要設(shè)置cer文件的路徑名稱亡鼠,以及是否需要https驗(yàn)證

代碼如下:
api

#import <Foundation/Foundation.h>
#import "NetStatusData.h"

@interface HttpRequstData : NSObject

+ (void)getUrl:(NSString*)url parameters:(NSDictionary*)parameters success:(void(^)(id responseObject)) success failure:(void(^)(NSError *error)) failure;

+(void)getNoHUDUrl:(NSString*)url parameters:(NSDictionary*)parameters success:(void(^)(id responseObject)) success failure:(void(^)(NSError *error)) failure;

+(void)postUrl:(NSString*)url parameters:(NSDictionary*)parameters showHUD:(BOOL)show success:(void(^)(id responseObject)) success failure:(void(^)(NSError *error)) failure;

+(void)postUrl:(NSString*)url parameters:(NSDictionary*)parameters success:(void(^)(id responseObject)) success failure:(void(^)(NSError *error)) failure;

+(void)postNoHUDUrl:(NSString*)url parameters:(NSDictionary*)parameters success:(void(^)(id responseObject)) success failure:(void(^)(NSError *error)) failure;

+ (nullable NSURLSessionDataTask *)POST:(NSString *)URLString
                             parameters:(nullable id)parameters
              constructingBodyWithBlock:(nullable void (^)(id <AFMultipartFormData> formData))block
                                success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
                                failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;

+ (nullable NSURLSessionDataTask *)POST:(NSString *)URLString
                             parameters:(nullable id)parameters
              constructingBodyWithBlock:(nullable void (^)(id <AFMultipartFormData> formData))block
                               progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgress
                                success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
                                failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;

@end

實(shí)現(xiàn)

#import "HttpRequstData.h"

/**
 *  是否開(kāi)啟https SSL 驗(yàn)證
 *
 *  @return YES為開(kāi)啟赏殃,NO為關(guān)閉
 */
#define openHttpsSSL YES
/**
 *  SSL 證書名稱,僅支持cer格式间涵∪嗜龋“app.bishe.com.cer”,則填“app.bishe.com”
 */
#define certificate @"public"

typedef NS_ENUM(NSInteger,HttpType) {
    GET,
    POST
};

static int timeOut = 30;

@interface HttpRequstData ()
{
    NSString *_url;
    NSDictionary *_parameters;
   
}
@property(nonatomic,strong)UILabel *tipsLable;

@end

@implementation HttpRequstData

+(void)getUrl:(NSString*)url parameters:(NSDictionary*)parameters success:(void(^)(id responseObject)) success failure:(void(^)(NSError *error)) failure
{
    [[NetStatusData shareNetStatus] checkNetStatus];
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    manager.requestSerializer.timeoutInterval = timeOut;
    // 加上這行代碼,https ssl 驗(yàn)證勾哩。
    if(openHttpsSSL)
    {
        [manager setSecurityPolicy:[self customSecurityPolicy]];
    }
    [MBProgressHUD showMessage:@"加載中..."];
     DDLog(@"parameters:%@",parameters);
    [manager GET:url parameters:parameters progress:^(NSProgress * _Nonnull downloadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        DDLog(@"====%@,%@==url:%@",responseObject,parameters,url);
        [MBProgressHUD hideHUD];
        //登陸成功===================================
        if ([responseObject[@"status"] isEqualToNumber:@500]) {
            [MBProgressHUD showSuccess:@"加載成功"];
            if (success) {
                success(responseObject);
            }
        }else{//登陸失敗=============================
            if ([responseObject[@"data"] isKindOfClass:[NSString class]]) {
                [MBProgressHUD showError:responseObject[@"data"]];
            }else{
                [MBProgressHUD showError:@"信息錯(cuò)誤"];
            }
            NSError *error1;
            failure(error1);
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        //         [[NetWorkingStausTipLabel shareNetWorkingStausTipLabel] showDuration:2.0];
        [MBProgressHUD hideHUD];
        [MBProgressHUD showError:@"網(wǎng)絡(luò)異常"];
        DDLog(@"%s==error--%@",__func__,error);
        if (error) {
            failure(error);
        }

    }];
}

+(void)getNoHUDUrl:(NSString*)url parameters:(NSDictionary*)parameters success:(void(^)(id responseObject)) success failure:(void(^)(NSError *error)) failure {
    [[NetStatusData shareNetStatus] checkNetStatus];
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    manager.requestSerializer.timeoutInterval = timeOut;
    // 加上這行代碼抗蠢,https ssl 驗(yàn)證。
    if(openHttpsSSL)
    {
        [manager setSecurityPolicy:[self customSecurityPolicy]];
    }
    DDLog(@"parameters:%@",parameters);
    [manager GET:url parameters:parameters progress:^(NSProgress * _Nonnull downloadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        DDLog(@"====%@,%@==url:%@",responseObject,parameters,url);
         [MBProgressHUD hideHUD];
        //登陸成功===================================
        if ([responseObject[@"status"] isEqualToNumber:@500]) {
            if (success) {
                success(responseObject);
            }
        }else{//登陸失敗=============================
            if ([responseObject[@"data"] isKindOfClass:[NSString class]]) {
                [MBProgressHUD showError:responseObject[@"data"]];
            }else{
                [MBProgressHUD showError:@"信息錯(cuò)誤"];
            }
            NSError *error1;
            failure(error1);
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        //         [[NetWorkingStausTipLabel shareNetWorkingStausTipLabel] showDuration:2.0];
        DDLog(@"%s==error--%@",__func__,error);
        [MBProgressHUD hideHUD];
        [MBProgressHUD showError:@"網(wǎng)絡(luò)異常"];
        if (error) {
            failure(error);
        }
        
    }];
}

#pragma mark-------封裝請(qǐng)求
+(void)postUrl:(NSString*)url parameters:(NSDictionary*)parameters showHUD:(BOOL)show success:(void(^)(id responseObject)) success failure:(void(^)(NSError *error)) failure {
    [[NetStatusData shareNetStatus] checkNetStatus];
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    manager.requestSerializer.timeoutInterval = timeOut;
    // 加上這行代碼思劳,https ssl 驗(yàn)證迅矛。
    if(openHttpsSSL)
    {
        [manager setSecurityPolicy:[self customSecurityPolicy]];
    }
    if (show) {
        [MBProgressHUD showMessage:@"加載中..."];
    }
    DDLog(@"parameters:%@==url:%@==",parameters,url);
    
    [manager POST:url parameters:parameters progress:^(NSProgress * _Nonnull uploadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        DDLog(@"====%@,%@==url:%@===parameters:%@",responseObject,responseObject[@"data"],url,parameters);
        if (show) {
            [MBProgressHUD hideHUD];
        }
        //登陸成功===================================
        if ([responseObject[@"status"] isEqualToNumber:@500]) {
            if ([responseObject[@"data"] isKindOfClass:[NSArray class]]) {
                if ([responseObject[@"data"] count] < 1) {
                    //                    [MBProgressHUD showSuccess:@"沒(méi)有更多數(shù)據(jù)"];
                }else{
                    if (show) {
                        //                        [MBProgressHUD showSuccess:@"加載成功"];
                    }
                }
            }else{
                if (show) {
                    //                    [MBProgressHUD showSuccess:@"加載成功"];
                }
            }
            if (success) {
                success(responseObject);
            }
        }else{//登陸失敗=============================
            if ([responseObject[@"data"] isKindOfClass:[NSString class]]) {
                //                if (show) {
                [MBProgressHUD showError:responseObject[@"data"]];
                //                }
            }else{
                //                if (show) {
                [MBProgressHUD showError:@"信息錯(cuò)誤"];
                //                }
            }
            NSError *error1;
            failure(error1);
        }
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        //         [[NetWorkingStausTipLabel shareNetWorkingStausTipLabel] showDuration:2.0];
        if (show) {
            [MBProgressHUD hideHUD];
        }
        //        [MBProgressHUD showError:@"請(qǐng)求失敗"];
        DDLog(@"%s==error--%@",__func__,error);
        if (error) {
            failure(error);
        }
    }];
}


+(void)postUrl:(NSString*)url parameters:(NSDictionary*)parameters success:(void(^)(id responseObject)) success failure:(void(^)(NSError *error)) failure
{
    [self postUrl:url parameters:parameters showHUD:YES success:success failure:failure];
}

+(void)postNoHUDUrl:(NSString*)url parameters:(NSDictionary*)parameters success:(void(^)(id responseObject)) success failure:(void(^)(NSError *error)) failure
{
    [self postUrl:url parameters:parameters showHUD:NO success:success failure:failure];
}


#pragma mark-------上傳圖片

+(NSURLSessionDataTask *)POST:(NSString *)URLString parameters:(id)parameters constructingBodyWithBlock:(void (^)(id<AFMultipartFormData>))block progress:(void (^)(NSProgress *))uploadProgress success:(void (^)(NSURLSessionDataTask *, id _Nullable))success failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError *))failure {
    
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    // 加上這行代碼,https ssl 驗(yàn)證潜叛。
    if(openHttpsSSL)
    {
        [manager setSecurityPolicy:[self customSecurityPolicy]];
    }
    return [manager POST:URLString parameters:parameters constructingBodyWithBlock:block progress:uploadProgress success:success failure:failure];
}

+(NSURLSessionDataTask *)POST:(NSString *)URLString parameters:(id)parameters constructingBodyWithBlock:(void (^)(id<AFMultipartFormData>))block success:(void (^)(NSURLSessionDataTask *, id _Nullable))success failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError *))failure {
    return [self POST:URLString parameters:parameters constructingBodyWithBlock:block progress:nil success:success failure:failure];
}

#pragma mark========https

+ (AFSecurityPolicy*)customSecurityPolicy
{
    // /先導(dǎo)入證書
    NSString *cerPath = [[NSBundle mainBundle] pathForResource:certificate ofType:@"cer"];//證書的路徑
    NSData *certData = [NSData dataWithContentsOfFile:cerPath];
    
    // AFSSLPinningModeCertificate 使用證書驗(yàn)證模式
    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
//    AFSSLPinningModeNone秽褒、AFSSLPinningModeCertificate
    // allowInvalidCertificates 是否允許無(wú)效證書(也就是自建的證書)壶硅,默認(rèn)為NO
    // 如果是需要驗(yàn)證自建證書,需要設(shè)置為YES
    securityPolicy.allowInvalidCertificates = YES;
    
    //validatesDomainName 是否需要驗(yàn)證域名震嫉,默認(rèn)為YES森瘪;
    //假如證書的域名與你請(qǐng)求的域名不一致,需把該項(xiàng)設(shè)置為NO票堵;如設(shè)成NO的話扼睬,即服務(wù)器使用其他可信任機(jī)構(gòu)頒發(fā)的證書,也可以建立連接悴势,這個(gè)非常危險(xiǎn)窗宇,建議打開(kāi)。
    //置為NO特纤,主要用于這種情況:客戶端請(qǐng)求的是子域名军俊,而證書上的是另外一個(gè)域名。因?yàn)镾SL證書上的域名是獨(dú)立的捧存,假如證書上注冊(cè)的域名是www.google.com粪躬,那么mail.google.com是無(wú)法驗(yàn)證通過(guò)的;當(dāng)然昔穴,有錢可以注冊(cè)通配符的域名*.google.com镰官,但這個(gè)還是比較貴的。
    //如置為NO吗货,建議自己添加對(duì)應(yīng)域名的校驗(yàn)邏輯泳唠。
    securityPolicy.validatesDomainName = NO;
    
    securityPolicy.pinnedCertificates = [[NSSet alloc] initWithObjects:certData,nil];
    return securityPolicy;
}

2、封裝網(wǎng)絡(luò)狀態(tài)監(jiān)測(cè)

思路:用了一個(gè)單例宙搬,每次請(qǐng)求接口的時(shí)候調(diào)用小網(wǎng)絡(luò)狀態(tài)監(jiān)測(cè)api
根據(jù)不同的網(wǎng)絡(luò)情況顯示提示

#import <Foundation/Foundation.h>

@interface NetStatusData : NSObject

@property(nonatomic,assign)AFNetworkReachabilityStatus status;//網(wǎng)絡(luò)狀態(tài)

+(NetStatusData*)shareNetStatus;

-(void)checkNetStatus;//檢查網(wǎng)絡(luò)狀態(tài)

@end
static NetStatusData *_netStatus = nil;

@implementation NetStatusData

+(NetStatusData *)shareNetStatus {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (!_netStatus) {
            _netStatus = [NetStatusData new];
        }
    });
    return _netStatus;
}

-(void)checkNetStatus {
    AFNetworkReachabilityManager *manager=[AFNetworkReachabilityManager sharedManager];
    __weak AFNetworkReachabilityManager *weakManager = manager;
    [manager startMonitoring];
    //檢測(cè)網(wǎng)絡(luò)狀態(tài)有網(wǎng)絡(luò)笨腥,網(wǎng)絡(luò)請(qǐng)求數(shù)據(jù),沒(méi)網(wǎng)絡(luò)提示
    [manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
        self.status = status;
        if (!status) {//未連接
            UIWindow *window = [[UIApplication sharedApplication].windows lastObject];
            UILabel *tipsLable;
            if (!tipsLable) {
                tipsLable = [[UILabel alloc] initWithFrame:(CGRect){kScreenWidth/2,kScreenHeight/2+80,110,33}];
                tipsLable.textColor = [UIColor whiteColor];
                tipsLable.textAlignment = NSTextAlignmentCenter;
                tipsLable.centerX = window.centerX;
                tipsLable.backgroundColor = [UIColor blackColor];
                tipsLable.text = @"網(wǎng)絡(luò)未連接";
            }
            [window addSubview:tipsLable];
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                [tipsLable removeFromSuperview];
            });
            
            return;
        }else{//連接請(qǐng)求數(shù)據(jù)
            //            [self requstData:type];
        }
        [weakManager stopMonitoring];
    }];
}

@end

3勇垛、數(shù)據(jù)解析層(核心思想)

注:利用基類做類別封裝請(qǐng)求脖母,可以直接用模型請(qǐng)求接口,并且封裝解析過(guò)程闲孤。根據(jù)不同的模型及json類型動(dòng)態(tài)解析數(shù)據(jù)谆级。后期代碼免去解析代碼

代碼分為兩部分,一部分代碼解析崭放,一部分?jǐn)?shù)據(jù)請(qǐng)求

1哨苛、數(shù)據(jù)請(qǐng)求

#import <Foundation/Foundation.h>

@interface NSObject (Request)
//請(qǐng)求數(shù)據(jù)
+(void)requestUrl:(NSString*)url parameters:(NSDictionary*)parameters showHUD:(BOOL)show success:(void(^)(id responseObject)) success failure:(void(^)(NSError *error)) failure;

+(void)requestUrl:(NSString*)url parameters:(NSDictionary*)parameters success:(void(^)(id responseObject)) success failure:(void(^)(NSError *error)) failure;

+(void)requestNoHUDUrl:(NSString*)url parameters:(NSDictionary*)parameters success:(void(^)(id responseObject)) success failure:(void(^)(NSError *error)) failure;
//解析數(shù)據(jù)
+(id)parseData:(id)responseObject;
//對(duì)象轉(zhuǎn)json
-(NSDictionary*)toJson;
//獲取屬性的類型
+(NSString*)getPropertyType:(NSString*)property;
-(NSString*)getPropertyType:(NSString*)property;

@end
#import "NSObject+Request.h"
#import <objc/runtime.h>

@implementation NSObject (Request)

+(void)requestUrl:(NSString*)url parameters:(NSDictionary*)parameters showHUD:(BOOL)show success:(void(^)(id responseObject)) success failure:(void(^)(NSError *error)) failure {
    [HttpRequstData postUrl:url parameters:parameters showHUD:show success:^(id responseObject) {
        id obj = [self parseData:responseObject[@"data"]];
        success(obj);
    } failure:^(NSError *error) {
        failure(error);
    }];
}

+(void)requestUrl:(NSString*)url parameters:(NSDictionary*)parameters success:(void(^)(id responseObject)) success failure:(void(^)(NSError *error)) failure {
    [self requestUrl:url parameters:parameters showHUD:YES success:success failure:failure];
}

+(void)requestNoHUDUrl:(NSString *)url parameters:(NSDictionary *)parameters success:(void (^)(id))success failure:(void (^)(NSError *))failure {
    [self requestUrl:url parameters:parameters showHUD:NO success:success failure:failure];
}

+(id)parseData:(id)responseObject {
    
    id obj;
    //單個(gè)對(duì)象
    if ([responseObject isKindOfClass:[NSDictionary class]]) {
        obj = [[self alloc]init];
        [obj setValuesForKeysWithDictionary:responseObject];
    }
    //        多個(gè)對(duì)象
    else if ([responseObject isKindOfClass:[NSArray class]]) {
        obj = [NSMutableArray new];
        for (NSDictionary *dic in responseObject) {
            id o = [[self alloc]init];
            [o setValuesForKeysWithDictionary:dic];
            [obj addObject:o];
        }
    }
    return obj;
}

-(NSDictionary *)toJson
{
    NSMutableDictionary *params = [NSMutableDictionary dictionary];
    unsigned  int count = 0;
    Ivar *ivars = class_copyIvarList(self.class, &count);
    for (int i = 0; i < count; i++) {
        const char *cname = ivar_getName(ivars[i]);
        NSString *name = [NSString stringWithUTF8String:cname];
        NSString *key = [name substringFromIndex:1];
        id value = [self valueForKey:key];
        if ([value isKindOfClass:[NSString class]]&&[(NSString*)value length]) {
            [params setValue:value forKey:key];
        }
    }
    return params;
}

#pragma mark-------//獲取屬性的類型

+(NSString *)getPropertyType:(NSString *)property {
    //獲取對(duì)象的類型objc_getClass("UserModel")
    objc_property_t p = class_getProperty(self, property.UTF8String);
  if (!p) {
        return nil;
    }
    const char *cname = property_getAttributes(p);
    DDLog(@"%s==",cname);
    // 2.成員類型
    NSString *attrs = @(property_getAttributes(p));
    NSUInteger dotLoc = [attrs rangeOfString:@","].location;
    NSString *code = nil;
    NSUInteger loc = 3;
    if (dotLoc == NSNotFound) { // 沒(méi)有,
        code = [attrs substringFromIndex:loc];
    } else {
        code = [attrs substringWithRange:NSMakeRange(loc, dotLoc - loc-1)];
    }
    DDLog(@"%@===%@====",code,attrs);
    return code;
}

-(NSString *)getPropertyType:(NSString *)property {
    //獲取對(duì)象的類型objc_getClass("UserModel")
    objc_property_t p = class_getProperty(self.class, property.UTF8String);
  if (!p) {
        return nil;
    }
    const char *cname = property_getAttributes(p);
    DDLog(@"%s==",cname);
    // 2.成員類型
    NSString *attrs = @(property_getAttributes(p));
    NSUInteger dotLoc = [attrs rangeOfString:@","].location;
    NSString *code = nil;
    NSUInteger loc = 3;
    if (dotLoc == NSNotFound) { // 沒(méi)有,
        code = [attrs substringFromIndex:loc];
    } else {
        code = [attrs substringWithRange:NSMakeRange(loc, dotLoc - loc-1)];
    }
    DDLog(@"%@===%@====",code,attrs);
    return code;
}


@end
2鸽凶、數(shù)據(jù)解析

思路:通過(guò)kvc解析數(shù)據(jù)币砂,判斷json的key值是否是json和數(shù)組是的話進(jìn)一步解析。不是的話直接賦值玻侥,解決復(fù)雜類型的json動(dòng)態(tài)解析决摧。
注意:數(shù)據(jù)字段的時(shí)候需要指明數(shù)據(jù)放的對(duì)象類型

使用時(shí)需要解析的模型類需要繼承Model類

/*
 *對(duì)象中含有的模型數(shù)據(jù)對(duì)應(yīng)的對(duì)象名稱例如
 *@{
    @"statuses" : @"Status",===字段有statuses的數(shù)組含有的對(duì)象為Status類型
 *};
 */
@property(nonatomic,strong)NSDictionary *classInArrayDic;

代碼如下

#import <Foundation/Foundation.h>
#import "NSObject+Request.h"

@interface Model : NSObject<NSCoding,NSCopying>

//對(duì)象轉(zhuǎn)json
-(NSDictionary*)toJson;
/*
 *對(duì)象中含有的模型數(shù)據(jù)對(duì)應(yīng)的對(duì)象名稱例如
 *@{
    @"statuses" : @"Status",===字段有statuses的數(shù)組含有的對(duì)象為Status類型
 *};
 */
@property(nonatomic,strong)NSDictionary *classInArrayDic;

@end
#import "Model.h"

@implementation Model

-(void)setValue:(id)value forKey:(NSString *)key{
    
    if ([value isKindOfClass:[NSNumber class]]) {
        [self setValue:[NSString stringWithFormat:@"%@",value] forKey:key];
    }else if ([value isKindOfClass:[NSArray class]]) {
        
    }else{
        if (!value||[value isKindOfClass:[NSNull class]]) {
            [super setValue:@"" forKey:key];
        }else{
            [super setValue:value forKey:key];
        }
    }
}

-(void)setValue:(id)value forUndefinedKey:(NSString *)key{
    
        if ([key isEqualToString:@"description"]) {
            [self setValue:value forKey:@"descriptionStr"];
        }else if ([key isEqualToString:@"id"]){
            [self setValue:value forKey:@"Id"];
        }else if([key isEqualToString:@"newPrice"]){
            [self setValue:value forKey:@"price"];
        }else if([key isEqualToString:@"code"]){
            [self setValue:value forKey:@"codePara"];
        }else{
            DDLog(@"沒(méi)有key==%@",key);
        }
}

-(void)setValuesForKeysWithDictionary:(NSDictionary<NSString *,id> *)keyedValues {
    for (NSString *key in keyedValues) {
        id value = keyedValues[key];
        //對(duì)象中含有對(duì)象數(shù)組
        if ([value isKindOfClass:[NSArray class]]) {
            if (![self.classInArrayDic objectForKey:key]) {
                DDLog(@"請(qǐng)給數(shù)組對(duì)象對(duì)應(yīng)類型");
                continue;
            }
            //設(shè)置數(shù)組的值
            NSMutableArray *values = [NSMutableArray new];
            //取出數(shù)組含有對(duì)象類型
            Class ObjectType = NSClassFromString(self.classInArrayDic[key]);
            DDLog(@"%@",ObjectType);
            for (NSDictionary *dic in value) {
                 //獲取對(duì)象類型生成實(shí)例
                id obj = [[ObjectType alloc]init];
                [obj setValuesForKeysWithDictionary:dic];
                [values addObject:obj];
            }
            [self setValue:values forKey:key];
        }else if ([value isKindOfClass:[NSDictionary class]]) {//對(duì)象中含有對(duì)象
            //獲取對(duì)象的類型
            NSString *type = [self getPropertyType:key];
            if (type.length) {
                DDLog(@"請(qǐng)給對(duì)象對(duì)應(yīng)類型");
                continue;
            }
            //獲取對(duì)象類型生成實(shí)例
            Class ObjectType = NSClassFromString(type);
            id obj = [[ObjectType alloc]init];
            [obj setValuesForKeysWithDictionary:value];
            [self setValue:obj forKey:key];
        }else {
            [self setValue:value forKey:key];
        }
    }
}

-(NSDictionary *)toJson
{
    NSMutableDictionary *params = [NSMutableDictionary dictionary];
    unsigned  int count = 0;
    Ivar *ivars = class_copyIvarList(self.class, &count);
    for (int i = 0; i < count; i++) {
        const char *cname = ivar_getName(ivars[i]);
        NSString *name = [NSString stringWithUTF8String:cname];
        NSString *key = [name substringFromIndex:1];
        id value = [self valueForKey:key];
        if ([value isKindOfClass:[NSString class]]&&[(NSString*)value length]) {
            [params setValue:value forKey:key];
        }
    }
    return params;
}

#pragma mark-------NSCoding,歸接檔協(xié)議,運(yùn)行時(shí)

- (void)encodeWithCoder:(NSCoder *)aCoder
{
    unsigned  int count = 0;
    Ivar *ivars = class_copyIvarList(self.class, &count);
    for (int i = 0; i < count; i++) {
        const char *cname = ivar_getName(ivars[i]);
        NSString *name = [NSString stringWithUTF8String:cname];
        NSString *key = [name substringFromIndex:1];
        id value = [self valueForKey:key];
        [aCoder encodeObject:value forKey:key];
    }
    
}
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder
{
    if (self = [super init]) {
        
        unsigned  int count = 0;
        Ivar *ivars = class_copyIvarList(self.class, &count);
        
        for (int i = 0; i < count; i++) {
            const char *cname = ivar_getName(ivars[i]);
            NSString *name = [NSString stringWithUTF8String:cname];
            NSString *key = [name substringFromIndex:1];
            id value = [aDecoder decodeObjectForKey:key];
            [self setValue:value forKey:key];
        }
    }
    return self;
}

-(id)copyWithZone:(NSZone *)zone {
    id copy = [[[self class] allocWithZone:zone] init];
    unsigned  int count = 0;
    Ivar *ivars = class_copyIvarList(self.class, &count);
    
    for (int i = 0; i < count; i++) {
        const char *cname = ivar_getName(ivars[i]);
        NSString *name = [NSString stringWithUTF8String:cname];
        NSString *key = [name substringFromIndex:1];
        id value = [self valueForKey:key];
        [copy setValue:value forKey:key];
    }
    return copy;
}


@end
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子掌桩,更是在濱河造成了極大的恐慌边锁,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,110評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件波岛,死亡現(xiàn)場(chǎng)離奇詭異茅坛,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)则拷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門贡蓖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人煌茬,你說(shuō)我怎么就攤上這事斥铺。” “怎么了坛善?”我有些...
    開(kāi)封第一講書人閱讀 165,474評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵晾蜘,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我眠屎,道長(zhǎng)剔交,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,881評(píng)論 1 295
  • 正文 為了忘掉前任组力,我火速辦了婚禮省容,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘燎字。我一直安慰自己腥椒,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,902評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布候衍。 她就那樣靜靜地躺著笼蛛,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蛉鹿。 梳的紋絲不亂的頭發(fā)上滨砍,一...
    開(kāi)封第一講書人閱讀 51,698評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音妖异,去河邊找鬼惋戏。 笑死,一個(gè)胖子當(dāng)著我的面吹牛他膳,可吹牛的內(nèi)容都是我干的响逢。 我是一名探鬼主播,決...
    沈念sama閱讀 40,418評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼棕孙,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼舔亭!你這毒婦竟也來(lái)了些膨?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,332評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤钦铺,失蹤者是張志新(化名)和其女友劉穎订雾,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體矛洞,經(jīng)...
    沈念sama閱讀 45,796評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡洼哎,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,968評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了沼本。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谱净。...
    茶點(diǎn)故事閱讀 40,110評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖擅威,靈堂內(nèi)的尸體忽然破棺而出壕探,到底是詐尸還是另有隱情,我是刑警寧澤郊丛,帶...
    沈念sama閱讀 35,792評(píng)論 5 346
  • 正文 年R本政府宣布李请,位于F島的核電站,受9級(jí)特大地震影響厉熟,放射性物質(zhì)發(fā)生泄漏导盅。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,455評(píng)論 3 331
  • 文/蒙蒙 一揍瑟、第九天 我趴在偏房一處隱蔽的房頂上張望白翻。 院中可真熱鬧,春花似錦绢片、人聲如沸滤馍。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,003評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)巢株。三九已至,卻和暖如春熙涤,著一層夾襖步出監(jiān)牢的瞬間阁苞,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,130評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工祠挫, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留那槽,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,348評(píng)論 3 373
  • 正文 我出身青樓等舔,卻偏偏與公主長(zhǎng)得像骚灸,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子软瞎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,047評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容