iOS 使用Manager 进行JSON解析数据及model处理

简介

  • Manager的使用相当于单例,即将需要用到的全局变量和解析数据的方法存入一个类中
  • 单例在整个生命周期中只需要创建一次,Manager同理,再考虑到唯一性及线程安全,在这里我们给Manager的创建加锁,若已经存在Manager便不再申请

代码及解析

Manager的创建

dispatch _once可以保证线程安全,static修饰全局变量:
在这里我将这个方法写成类方法,方便以后调用

+ (instancetype)sharedManger {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (manger == nil) {
            manger = [[BeanFlapMainViewManger alloc] init];
        }
    });
    return manger;
}

数据请求函数

我使用块(block)进行传值

//成功返回对应的model
typedef void (^BFMainViewNowBlock)(BeanFlapMainViewModel *mainViewNowModel);
//失败返回error
typedef void (^ErrorBlock)(NSError * _Nonnull error);

NS_ASSUME_NONNULL_BEGIN

@interface BeanFlapMainViewManger : NSObject

+ (instancetype)sharedManger;

//获取影院热映数据
- (void)fetchMainViewFilmSucceed:(BFMainViewNowBlock) succeedBlock error:(ErrorBlock) errorBlock;

@end

NS_ASSUME_NONNULL_END

函数:
我以最近在写的豆瓣的请求为例

- (void)fetchMainViewFilmSucceed:(BFMainViewNowBlock)succeedBlock error:(ErrorBlock)errorBlock {
	//普普通通的网络请求
    NSString *filmNowURLStr = [NSString stringWithFormat:@"http://douban.uieee.com/v2/movie/in_theaters"];
    NSURL *filmNowURL = [NSURL URLWithString:filmNowURLStr];
    NSURLRequest *filmNowURLRequest = [NSURLRequest requestWithURL:filmNowURL];
    NSURLSession *filmNowURLSeesion = [NSURLSession sharedSession];
    NSURLSessionDataTask *filmNowDataTask = [filmNowURLSeesion dataTaskWithRequest:filmNowURLRequest completionHandler:^(NSData *_Nullable data, NSURLResponse * _Nullable response, NSError *_Nullable error) {
        if (error == nil) {
            NSDictionary *getDictionary = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
            BeanFlapMainViewModel *filmNowModel = [[BeanFlapMainViewModel alloc] initWithDictionary:getDictionary error:&error];
            //成功返回请求到的数据
            succeedBlock(filmNowModel);
        } else {
            errorBlock(error);
        }
    }];
    [filmNowDataTask resume];
}

使用

在你需要用它的时候先创建后调用方法就行

    [[BeanFlapMainViewManger sharedManger] fetchMainViewFilmSucceed:^(BeanFlapMainViewModel *resultModel){
        self.myView.headView.myModel = [[BeanFlapMainViewModel alloc] init];
        self.myView.headView.myModel = resultModel;
        BFSubjectsModel *subjectModel = [[BFSubjectsModel alloc] init];
        subjectModel = self -> _myModel.subjects[0];
    } error: ^(NSError *error) {
        NSLog(@"---  error");
    }];
    [_myView.tableView reloadData];

和Model的配合

一般我们在使用时,将获取到的字典数据赋给model(该model继承于JSONModel),只需要Model的属性和数据解析出的名字一样,JSONModel会自动解析进行赋值,这就是JSONModel的强大之处
在嵌套数据时, 我们应该对每一个要嵌套的都写成一个类,但并不是意味着要写成多个类文件,而是只需要在一个类文件里把该有的写好就行
例如这是我请求到的字典数据:

{
    "count":20,
    "start":0,
    "total":61,
    "subjects":[
        {
            "rating":{
                "max":10,
                "average":8.6,
                "details":{
                    "1":214,
                    "2":185,
                    "3":1298,
                    "4":5897,
                    "5":6350
                },
                "stars":"45",
                "min":0
            },
            "genres":[
                "剧情",
                "爱情"
            ],
            "title":"少年的你",
            "casts":[
                {
                    "avatars":{
                        "small":"http://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p36798.webp",
                        "large":"http://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p36798.webp",
                        "medium":"http://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p36798.webp"
                    },
                    "name_en":"Dongyu Zhou",
                    "name":"周冬雨",
                    "alt":"https://movie.douban.com/celebrity/1274224/",
                    "id":"1274224"
                },
                {
                    "avatars":{
                        "small":"http://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1507879990.66.webp",
                        "large":"http://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1507879990.66.webp",
                        "medium":"http://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1507879990.66.webp"
                    },
                    "name_en":"Jackson Yee",
                    "name":"易烊千玺",
                    "alt":"https://movie.douban.com/celebrity/1340022/",
                    "id":"1340022"
                },
                {
                    "avatars":{
                        "small":"http://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1561012942.87.webp",
                        "large":"http://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1561012942.87.webp",
                        "medium":"http://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1561012942.87.webp"
                    },
                    "name_en":"Fang Yin",
                    "name":"尹昉",
                    "alt":"https://movie.douban.com/celebrity/1340310/",
                    "id":"1340310"
                }
            ],
            "durations":[
                "135分钟"
            ],
            "collect_count":161569,
            "mainland_pubdate":"2019-10-25",
            "has_video":false,
            "original_title":"少年的你",
            "subtype":"movie",
            "directors":Array[1],
            "pubdates":Array[1],
            "year":"2019",
            "images":Object{...},
            "alt":"https://movie.douban.com/subject/30166972/",
            "id":"30166972"
        },
        {
            "rating":{
                "max":10,
                "average":7.1,
                "details":{
                    "1":146,
                    "2":1376,
                    "3":10117,
                    "4":10166,
                    "5":2509
                },
                "stars":"35",
                "min":0
            },
            "genres":[
                "剧情",
                "动作",
                "科幻"
            ],
            "title":"双子杀手",
            "casts":[
                {
                    "avatars":{
                        "small":"http://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p41483.webp",
                        "large":"http://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p41483.webp",
                        "medium":"http://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p41483.webp"
                    },
                    "name_en":"Will Smith",
                    "name":"威尔·史密斯",
                    "alt":"https://movie.douban.com/celebrity/1027138/",
                    "id":"1027138"
                },
                {
                    "avatars":{
                        "small":"http://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p32684.webp",
                        "large":"http://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p32684.webp",
                        "medium":"http://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p32684.webp"
                    },
                    "name_en":"Mary Elizabeth Winstead",
                    "name":"玛丽·伊丽莎白·温斯特德",
                    "alt":"https://movie.douban.com/celebrity/1041018/",
                    "id":"1041018"
                },
                {
                    "avatars":{
                        "small":"http://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p5321.webp",
                        "large":"http://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p5321.webp",
                        "medium":"http://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p5321.webp"
                    },
                    "name_en":"Clive Owen",
                    "name":"克里夫·欧文",
                    "alt":"https://movie.douban.com/celebrity/1025147/",
                    "id":"1025147"
                }
            ],
            "durations":[
                "117分钟"
            ],
            "collect_count":125796,
            "mainland_pubdate":"2019-10-18",
            "has_video":false,
            "original_title":"Gemini Man",
            "subtype":"movie",
            "directors":[
                {
                    "avatars":{
                        "small":"http://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p595.webp",
                        "large":"http://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p595.webp",
                        "medium":"http://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p595.webp"
                    },
                    "name_en":"Ang Lee",
                    "name":"李安",
                    "alt":"https://movie.douban.com/celebrity/1054421/",
                    "id":"1054421"
                }
            ],
            "pubdates":[
                "2019-10-11(美国)",
                "2019-10-18(中国大陆)"
            ],
            "year":"2019",
            "images":{
                "small":"http://img1.doubanio.com/view/photo/s_ratio_poster/public/p2570906505.webp",
                "large":"http://img1.doubanio.com/view/photo/s_ratio_poster/public/p2570906505.webp",
                "medium":"http://img1.doubanio.com/view/photo/s_ratio_poster/public/p2570906505.webp"
            },
            "alt":"https://movie.douban.com/subject/3097572/",
            "id":"3097572"
        }
    ],
    "title":"正在上映的电影-北京"
}

我现在想获取它的电影名及图片和评分,但是很明显,它们没在同一层,那么需要多个model嵌套使用,即:

#import "JSONModel.h"

@protocol BFSubjectsModel

@end

NS_ASSUME_NONNULL_BEGIN

@interface BFRatingModel : JSONModel

@property (nonatomic) double average;

@end

@interface BFImagesModel : JSONModel

@property (nonatomic, strong) NSString *medium;

@end

@interface BFSubjectsModel : JSONModel
@property (nonatomic, strong) BFRatingModel *rating;
@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong) BFImagesModel *images;
@end

@interface BeanFlapMainViewModel : JSONModel

@property (nonatomic, strong) NSString *total;
@property (nonatomic, copy) NSArray<BFSubjectsModel> *subjects;

@end


NS_ASSUME_NONNULL_END

model的.m文件只需要写一个函数,该函数用于 就算API中没有请求到类中的,映射有问题也不会报错(直接忽略)

#import "BeanFlapMainViewModel.h"

@implementation BeanFlapMainViewModel

+(BOOL)propertyIsOptional:(NSString *)propertyName{
    return  YES;
}

@end

@implementation BFSubjectsModel

+(BOOL)propertyIsOptional:(NSString *)propertyName{
    return  YES;
}

@end

@implementation BFRatingModel

+(BOOL)propertyIsOptional:(NSString *)propertyName{
    return  YES;
}

@end

@implementation BFImagesModel

+(BOOL)propertyIsOptional:(NSString *)propertyName{
    return  YES;
}


@end

猜你喜欢

转载自blog.csdn.net/streamery/article/details/102762737
今日推荐