iOS——Manage封装一个网络请求
我们一般去写网络请求的时候,都是将网络请求写在viewDidLoad中,但现实中却不是这么简单的,我们需要有不同的网络请求的时候就可以用单例模式,创建一个全局的Manage类,用实例Manage来执行网络请求方法,顺便用Manage传递请求数据,在model里完成数据解析。单例在整个生命周期中只需要创建一次,Manager同理,再考虑到唯一性及线程安全,在这里我们给Manager的创建加锁,若已经存在Manager便不再申请。
核心代码
我们需要用block进行传值,在对应的Manager.h文件中:
//块定义 定义一个block 类型的变量 SuccesBlock 为输入参数 其需要参数类型是id 返回值是第二个括号 的块
//这样就可以利用 SuccesBlock进行参数的传递或者是编辑。
typedef void (^TestSucceedBlock)(TestModel * _Nonnull mainViewNowModel);
//失败返回error
typedef void (^ErrorBlock)(NSError * _Nonnull error);
@interface Manager : NSObject
+ (instancetype)sharedManger;//定义类方法
//获取数据函数
- (void)NetWorkTestWithData:(TestSucceedBlock) succeedBlock error:(ErrorBlock) errorBlock;
@end
首先因为dispatch _once可以保证线程安全,static修饰全局变量:然后我们将这个方法写成类方法通过GCD多线程方式实现单例:
+ (instancetype)sharedManger {
//1.如果onceToken=0时,线程执行dispatch_once的block中代码
//2.当onceToken=-1时,线程跳过dispatch_once的block中代码不执行
//3.当onceToken为其他值时,线程被阻塞,等待onceToken值改变
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (manger == nil) {
manger = [[BeanFlapMainViewManger alloc] init];
}
});
return manger;
}
//执行流程:
/*1.当线程调用shareInstance,此时onceToken = 0,调用block中的代码。
2.当其他线程再调用shareInstance方法时,onceToken的值已经是非0非-1的,线程阻塞。
3.当block线程执行完block之后,onceToken变为-1.其他线程不再阻塞,跳过block。
4.下次再调用shareInstance时,block已经为-1.直接跳过block。*/
然后我们将.h文件中的获取数据方法进行实现:
-(void)NetWorkTestWithData:(TestSucceedBlock)succeedBlock error:(ErrorBlock)errorBlock{
NSString *json = @"http://news-at.zhihu.com/api/4/news/latest";
json = [json stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSURL *testUrl = [NSURL URLWithString:json];
NSURLRequest *testRequest = [NSURLRequest requestWithURL:testUrl];
NSURLSession *testSession = [NSURLSession sharedSession];
NSURLSessionDataTask *testDataTask = [testSession dataTaskWithRequest:testRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error == nil) {
TestModel *country = [[TestModel alloc] initWithData:data error:nil];
succeedBlock(country);
} else {
errorBlock(error);
}
}];
//任务启动
[testDataTask resume];
}
然后在ViewController.m中:
-(void)test{
[[Manager sharedManger] NetWorkTestWithData:^(TestModel * _Nonnull mainViewNowModel) {
NSLog(@"%@",mainViewNowModel.stories[0]);
NSLog(@"请求成功");
} error:^(NSError * _Nonnull error) {
NSLog(@"请求失败");
}];
}
我们在需要使用的时候:
[self test];//就可以直接调用了