所以JSONModel就是Objective-c的一个开源第三方库,他可以帮我们处理网络请求到的数据,当我们向服务器发送一个请求之后,通过JSONModel把数据转成model就可以很方便我们使用了。
首先是需要配置环境,当配置好环境后才可以使用JSONModel。
首先要在终端中配置CocoaPod,这边可以参考一下之前写的一篇文章,Masonry。
接下来打开终端,cd到需要使用JSONModel的目录,输入touch Podfile文件,打开Podfile文件,修改文件内容为以下:
platform:ios,'9.0'
target 'JSONModel' do
pod 'JSONModel'
end
然后保存文件,在终端输入pod install这样就配置完成了
现在有一个知乎接口如下:
https://news-at.zhihu.com/api/4/version/ios/2.3.0
这是他的JSON数据:
{
"status":1,
"msg":"【更新内容】\r\n\r\n★ 多图有标记 流量壕忽略\r\n★ 出门前离线 没网也能看\r\n★ 喜欢请好评 不喜快吐槽\r\n★ 萌妹工程师 邮箱在下面\r\[email protected]\r\n(一般人我们不告诉他)",
"latest":"2.5"
}
之前我们需要使用字典去存储接受到的数据,现在我们利用JSONModel可以创建Model模型去直接接受数据。
创建一个TextModel继承JSONModel类
,属性对应JSON数据的名称。
@interface TestModel : JSONModel
@property (nonatomic, assign) int status;
@property (nonatomic, copy) NSString *msg;
@property (nonatomic, copy) NSString *latest;
这里属性的和JSON的值相对应,如果你传入的JSON合法,那么JSONModel会尝试转化数据为你期望的类型。JSONValueTransformer类支持许多转换:
NSMutableString <-> NSString
NSMutableArray <-> NSArray
NS(Mutable)Array <- JSONModelArray
NSMutableDictionary <-> NSDictionary
NSSet <-> NSArray
BOOL <-> number/string
string <-> number
string <-> url
string <-> time zone
string <-> date
number <-> date
接下来需要使用网络请求获得JSON数据。
//
// ViewController.m
// JSONModelDemo
//
// Created by 差不多先生 on 2021/10/11.
//
#import "ViewController.h"
#import "TextModel.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
NSString* json = @"https://news-at.zhihu.com/api/4/version/ios/2.3.0";
json = [json stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSURL* textUrl = [NSURL URLWithString:json];
NSURLRequest* textRequest = [NSURLRequest requestWithURL:textUrl];
NSURLSession* textSession = [NSURLSession sharedSession];
NSURLSessionDataTask *testDataTask = [textSession dataTaskWithRequest:textRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//这个TestModel就是上面说到的类
TextModel* country = [[TextModel alloc] initWithData:data error:nil];
NSLog(@"%@",country);
}];
//任务启动
[testDataTask resume];
}
@end
最后就完成了一个简单的JSONMOdel的使用。
我们需要将网络请求单独出来,如何进行网络请求,这里可以用单例模式,创建一个全局的Manger类,用实例manger来执行网络请求方法,顺便用manger传递请求数据,在model里完成数据解析。
1.在iOS开发过程中,需要使用到一些全局变量以及管理方法,可以将这些变量以及方法封装在一个管理类中,这是符合MVC开发模式的,这就需要使用单例(singleton)。
2.使用单例模式的变量在整个程序中只需要创建一次,而它生命周期是在它被使用时创建一直到程序结束后进行释放的,类似于静态变量,所以我们需要考虑到它的生命周期,唯一性以及线程安全。在这里,我们需要实用GCD来实现单例模式:
(保证线程安全, 不能确定代码的执行顺序,线程是不安全的)
这里有两种方式去创建单例。
1.
//
// Manager.m
// JSONModelDemo
//
// Created by 差不多先生 on 2021/10/14.
//
#import "Manager.h"
static Manager* manager = nil;
@implementation Manager
+(instancetype)shareManager {
i f (!manager) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager = [Manager new];
});
}
return manager;
}
@end
代码中的dispatch_once_t
:可以保证某段代码在程序运行过程中只被执行 1 次,并且即使在多线程的环境下,dispatch _once也可以保证线程安全。
还有一种方法:
2.
static id obj = nil;
+(instancetype)shareManager
{
@synchronized(self) {
if (!obj) {
obj = [[Manager alloc] init];
}
}
return obj;
}
这里利用@synchronized
加了一把锁,防止其他线程对代码块访问,但性能低,不推荐使用。
可以看到数据涉及数组以及嵌套,我们可以在一个类文件写多个Model。
//
// TextModel.h
// JSONModelDemo
//
// Created by 差不多先生 on 2021/10/11.
//
@protocol StoriesModel
@end
@protocol Top_StoriesModel
@end
#import <JSONModel/JSONModel.h>
NS_ASSUME_NONNULL_BEGIN
@interface StoriesModel : JSONModel
@property (nonatomic, copy) NSString* image_hue;
@property (nonatomic, copy) NSString* title;
@property (nonatomic, copy) NSString* url;
@property (nonatomic, copy) NSString* hint;
@property (nonatomic, copy) NSString* ga_prefix;
@property (nonatomic, copy) NSString* type;
@property (nonatomic, copy) NSString* id;
@end
@interface Top_StoriesModel : JSONModel
@property (nonatomic, copy) NSString* image_hue;
@property (nonatomic, copy) NSString* hint;
@property (nonatomic, copy) NSString* url;
@property (nonatomic, copy) NSString* title;
@property (nonatomic, copy) NSString* ga_prefix;
@property (nonatomic, copy) NSString* type;
@property (nonatomic, copy) NSString* id;
@end
@interface TextModel : JSONModel
@property (nonatomic, copy) NSString *date;
@property (nonatomic, copy) NSArray<StoriesModel> *stories;
@property (nonatomic, copy) NSArray<Top_StoriesModel > *top_stories;
@end
NS_ASSUME_NONNULL_END
在.m文件中实现类
#import "TextModel.h"
@implementation Top_StoriesModel
// 重写此方法可以避免服务器的数据没有返回nil而崩溃
+ (BOOL)propertyIsOptional:(NSString *)propertyName {
return YES;
}
@end
@implementation StoriesModel
+ (BOOL)propertyIsOptional:(NSString *)propertyName {
return YES;
}
@end
@implementation TextModel
+ (BOOL)propertyIsOptional:(NSString *)propertyName {
return YES;
}
@end
首先定义两个block块去调用数据,再定义一个方法在Manager中进行网络请求。
#import <Foundation/Foundation.h>
#import "TextModel.h"
// 请求到的数据作为参数调用block
typedef void (^GetJSONBlock)(TextModel * _Nonnull mainModel);// 传递接受到的数据
typedef void (^ErrorBlock)(NSError * _Nonnull error);// 请求失败返回error
NS_ASSUME_NONNULL_BEGIN
@interface Manager : NSObject
+(instancetype)shareManager;
-(void)NetworkQuestSuccess:(GetJSONBlock) GetJSONBlock error:(ErrorBlock) errorBlock;
@end
NS_ASSUME_NONNULL_END
.m文件
#import "Manager.h"
static Manager* manager = nil;
@implementation Manager
+(instancetype)shareManager {
if (!manager) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager = [Manager new];
});
}
return manager;
}
- (void)NetworkQuestSuccess:(GetJSONBlock)GetJSONBlock error:(ErrorBlock)ErrorBlock {
NSString* URLString = @"https://news-at.zhihu.com/api/4/news/latest";
// 处理中文
URLString = [URLString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
// 创建一个网络请求
NSURL* textUrl = [NSURL URLWithString:URLString];
NSURLRequest* textRequest = [NSURLRequest requestWithURL:textUrl];
// 创建网络请求会话
NSURLSession* textSession = [NSURLSession sharedSession];
// 创建一个请求任务
NSURLSessionDataTask* textDataTask = [textSession dataTaskWithRequest:textRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error == nil) {
TextModel* ansModel = [[TextModel alloc] initWithData:data error:nil];
GetJSONBlock(ansModel);
} else {
ErrorBlock(error);
}
}];
// 任务启动
[textDataTask resume];
}
@end
最后在ViewController使用即可
- (void)viewDidLoad {
[super viewDidLoad];
[self text];
}
-(void)text{
[[Manager shareManager] NetworkQuestSuccess:^(TextModel * _Nonnull mainViewNowModel) {
NSLog(@"%@",mainViewNowModel.stories[0]);
NSLog(@"请求成功");
} error:^(NSError * _Nonnull error) {
NSLog(@"请求失败");
}];
}
以上就是JSONModel的简单使用。
下面是完整Demo的地址:
JSONModel。