相比较将网络请求(使用AFNetWorking库)写到VIiewController中,在实际使用中并不是那么简单,我们需要不同的网络请求。这时我们需要使用到全局变量和管理方法,可以将这些变量以及方法封装在一个管理类中,这是符合MVC开发模式,这就需要使用单例,创建一个全局的Manager类,用实例Manager来执行网络请求方法,并将请求到的数据传递到其他文件或者在Model中完成数据解析。
需要导入的第三方库
platform :ios, '8.0'
target 'testAFNetworking' do
pod 'Masonry'
pod 'JSONModel'
pod 'AFNetworking', '~>3.0.0'
end
项目里的单例
#import "Manager.h"
#import <AFNetworking/AFNetworking.h>
#import <JSONModel/JSONModel.h>
#import "Model.h"
static Manager* manager = nil;
@implementation Manager
+ (instancetype) shareManager {
if (!manager) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager = [[Manager alloc] init];
});
}
return manager;
}
->>这里使用static修饰全局变量,其作用域仅限于当前文件,外部类是不可访问到该全局变量,这样就保证了manager实例不会改变,这样就保证了单例对象的唯一性。
->>使用dispatch_once_t方法,保证某段代码在程序运行中只被执行一次,即使在多线程的环境下,也可以保证线程安全。
项目中的JSONModel
什么是JSONModel
JSONModel:一个解析JSON数据的开源库,可以将JOSN数据直接解析成自定义的model
JSONModel的使用
创建一个继承与JOSONModel类的Model类,
这个类用于存放有关网络请求到的数据
以知乎日报的最新消息的接口为例
https://news-at.zhihu.com/api/4/news/latest
解析到的数据
根据解析到的数据创建成员变量
Model.h
//声明网络请求中要接受数据的两个协议
@protocol storiesModel
@end
@protocol top_StoriesModel
@end
#import "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) NSArray* images;
@property (nonatomic, copy) NSString* id;
@property (nonatomic, copy) NSString* type;
@end
@interface top_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* image;
@property (nonatomic, copy) NSString* type;
@property (nonatomic, copy) NSString* id;
@end
@interface Model : JSONModel
@property (nonatomic, copy) NSString* data;
@property (nonatomic, copy) NSArray<storiesModel>* stories;
@property (nonatomic, copy) NSArray<top_StoriesModel>* top_stories;
@end
NS_ASSUME_NONNULL_END
Model.m
#import "Model.h"
@implementation Model
+ (BOOL) propertyIsOptional:(NSString *)propertyName {
return YES;
}
@end
@implementation storiesModel
+ (BOOL) propertyIsOptional:(NSString *)propertyName {
return YES;
}
@end
@implementation top_StoriesModel
+ (BOOL) propertyIsOptional:(NSString *)propertyName {
return YES;
}
@end
->> + (BOOL)propertyIsOptional:(NSString *)propertyName 作用是不想因为服务器的某个值没有返回(nil)就使程序崩溃, 我们会加关键字Optional,如果不想每一条属性都添加,我们也可以在.m文件中重写方法.
项目中的Manager
其实Manager分装一个网络请求就是把之前的网络请求的代码写在一个函数中,调用该函数就实现了网络请求。这里使用的是ANFNeyworking库的网络请求。
同时这里使用了Block传值将请求到的数据传给其他文件
Manager.h
#import <Foundation/Foundation.h>
#import "Model.h"
NS_ASSUME_NONNULL_BEGIN
//创建两个Block块,返回成功获取到的数据
typedef void (^TestSucceedBlock) (Model* ViewModel);//返回Model类型的数据,TestSucceedBlock是该Block的名字
typedef void (^EorrorBlock) (NSError* error);
@interface Manager : NSObject
+ (instancetype) shareManager;
+//封装网络请求的函数,BLOCK会通过该函数返回网络请求货渠道的参数
- (void) makeData: (TestSucceedBlock) succeedBlock error:(EorrorBlock) errorBlock;
@end
NS_ASSUME_NONNULL_END
Manager.m
#import "Manager.h"
#import <AFNetworking/AFNetworking.h>
#import <JSONModel/JSONModel.h>
#import "Model.h"
static Manager* manager = nil;
@implementation Manager
+ (instancetype) shareManager {
if (!manager) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager = [[Manager alloc] init];
});
}
return manager;
}
- (void)makeData:(TestSucceedBlock)succeedBlock error:(EorrorBlock)errorBlock {
NSString* urlString = @"https://news-at.zhihu.com/api/4/news/latest";
AFHTTPSessionManager* manager = [AFHTTPSessionManager manager];
//manager.requestSerializer = [AFHTTPRequestSerializer serializer];
[manager GET:urlString parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
//将请求到的数据解析成自定义的Model
Model* JsonModelX = [[Model alloc] initWithDictionary:responseObject error:nil];
//NSLog(@"%@", responseObject);
//使用block传值将数据传回
succeedBlock(JsonModelX);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
errorBlock(error);
}];
}
@end
在ViewController创建单例对象,调用网络请求函数,同时调用Block的文件获取网络请求的数据
#import "ViewController.h"
#import "Model.h"
#import "Manager.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[[Manager shareManager] makeData:^(Model * _Nonnull ViewModel) {
NSLog(@"1111");
NSLog(@"%@", ViewModel.stories[0]);
} error:^(NSError * _Nonnull error) {
NSLog(@"请求失败");
}];
}
@end