1.在iOS开发过程中,需要使用到一些全局变量以及管理方法,可以将这些变量以及方法封装在一个管理类中,这是符合MVC开发模式的,这就需要使用单例(singleton)。
2.使用单例模式的变量在整个程序中只需要创建一次,而它生命周期是在它被使用时创建一直到程序结束后进行释放的,类似于静态变量,所以我们需要考虑到它的生命周期,唯一性以及线程安全。在这里,我们需要实用GCD来实现单例模式:
(保证线程安全, 不能确定代码的执行顺序,线程是不安全的)
不过GCD我还只是了解了一下概念,在这里的单例模式中的体现应该就是锁的使用 ;
下面是GCD的概念 ;
GCD (Grand Central Dispatch) 是苹果公司提供的一种多核编程的解决方案,用于简化多线程编程和并发任务的调度。它是一种基于队列的执行模型,可以有效地利用系统上可用的处理器内核,从而提高应用程序的性能和响应性。
单例模式其实有很多种实现方式,这里就只写了一种,也是demo里用到的 ;看代码 ;
static Manager* manager = nil ;
@implementation Manager
+ (instancetype)shareSingleton {
if (!manager) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager = [[Manager alloc] init] ;
});
}
return manager;
}
dispatch_once 是 GCD 提供的一个函数,用于确保代码块只执行一次。它通常用于实现单例模式或执行一次性初始化的任务。
这里的manager对网络请求的封装实际上就是将网络请求方法的调用放在manager单例的方法中,实现通过manager单例调用方法实现网络请求,而无需了解网络请求中的详细带代码 ;
这里用到的block传值 ;
#import <Foundation/Foundation.h>
#import "TestModel.h"
typedef void(^TestModelBlock)(TestModel* _Nullable mainModel);
typedef void(^ErrorModelBlack)(NSError* _Nullable error);
NS_ASSUME_NONNULL_BEGIN
@interface Manager : NSObject
+ (instancetype)shareSingleton ;
- (void)NetWorkGetWithData : (TestModelBlock) mainModelBolack andError : (ErrorModelBlack) errorBlock ;
@end
NS_ASSUME_NONNULL_END
上面的NetWorkGetWithData方法可以实现网络·请求的全过程 ;
该方法通过两个Block参数传回网络请求到的数据和请求失败时的error ;
.m文件
- (void) NetWorkGetWithData:(TestModelBlock)mainModelBolack andError:(ErrorModelBlack)errorBlock {
NSString* jsonstr = @"https://news-at.zhihu.com/api/4/news/latest" ;
jsonstr = [jsonstr stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]] ;
NSURL* testurl = [NSURL URLWithString:jsonstr] ;
NSURLRequest* resquest = [NSURLRequest requestWithURL:testurl] ;
// AFURLSessionManager* sessionmanager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]] ;
NSURLSession* session = [NSURLSession sharedSession] ;
NSURLSessionTask* sessiontask = [session dataTaskWithRequest:resquest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error) {
errorBlock(error) ;
} else {
TestModel* model = [[TestModel alloc] initWithData:data error:nil] ;
mainModelBolack(model) ;
// NSLog(@"%@",model) ;
self.model01 = model.stories[1] ;
// NSLog(@"%@",model.stories[0]) ;
}
}] ;
[sessiontask resume] ;
}
NSString* jsonstr = @"https://news-at.zhihu.com/api/4/news/latest" ;
jsonstr = [jsonstr stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]] ;
NSURL* testurl = [NSURL URLWithString:jsonstr] ;
NSURLRequest* resquest = [NSURLRequest requestWithURL:testurl] ;
// AFURLSessionManager* sessionmanager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]] ;
NSURLSession* session = [NSURLSession sharedSession] ;
NSURLSessionTask* sessiontask = [session dataTaskWithRequest:resquest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error) {
NSLog(@"Error: %@",error) ;
} else {
TestModel* model = [[TestModel alloc] initWithData:data error:nil] ;
NSLog(@"%@",model) ;
// self.model01 = model.stories[1] ;
NSLog(@"%@",model.stories[0]) ;
self.Model = model.stories[0] ;
// NSLog(@"%d",self.Model == nil) ;
NSLog(@"%@",self.Model.title) ;
NSDictionary* dict = [[NSDictionary alloc] init] ;
dict = [model toDictionary];
NSLog(@"%@", dict[@"stories"][0][@"title"]) ;
}
}] ;
[sessiontask resume] ;
“JSONModel” 可以指代以下两种不同的概念:
JSONModel 数据模型:这是一种将 JSON 数据映射到编程语言对象的模型。它描述了如何定义和组织对象,以便与 JSON 数据进行相应的转换。JSONModel 数据模型通常使用注解、属性映射或配置文件等方式,将 JSON 数据的键值对映射到对象的属性。这种模型可以简化开发人员在处理 JSON 数据时的操作,提供了方便的访问和操作方式。
JSONModel 框架:这是一个特定的软件框架或库,用于在特定编程语言中实现 JSON 数据模型的转换。这样的框架通常提供了一组工具和方法,用于将 JSON 数据解析为对象、将对象序列化为 JSON 数据,以及处理对象属性和嵌套关系等。JSONModel 框架可以根据特定编程语言的需求和约定,提供更高层次的抽象和功能,以简化 JSON 数据的处理。
iOS中就这里的使用应该只涉及到了JSONModel 数据模型 ;
我们这里的jsonModel使用的步骤:
1.pod引入jsonModel的第三方库
2.将网络请求到的data转化为jsonModel类对象存储 ;
3.将jsonModel类对象转化为字典,然后输出(非必要)
引入第三方库的方法可以看我之前的博客,其他步骤基本不变,只需将podfile中的代码改为**pod ‘JSONModel’**就行了 ;
首先,我们要创建一个jsonModel的子类,但这里我们的uRL请求到的数据分类较复杂,所以这里创建了多个子类 ;
#import "JSONModel.h"
#import <JSONModel/JSONModel.h>
NS_ASSUME_NONNULL_BEGIN
@protocol storiesModel
@end
@protocol top_StoriesModel
@end
@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;
@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;
@end
@interface TestModel : 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
上面的两个协议其实没有声明任何方法,他们的作用在给定的代码中,@protocol 关键字用于定义两个协议,分别是 storiesModel 和 top_StoriesModel。这些协议可能用于指定特定的数据模型类型。更像是两个标记
在.m文件中要注意重写一个方法,+ (BOOL)propertyIsOptional:(NSString *)propertyName
,如果不重写这个方法,可能会导致程序奔溃,但不绝对 ;
注意属性的名字要与接受到字典的key一一对应,不然会无法请求数据,甚至导致程序奔溃
TestModel* model = [[TestModel alloc] initWithData:data error:nil] ;
NSLog(@"%@",model) ;
// self.model01 = model.stories[1] ;
NSLog(@"%@",model.stories[0]) ;
self.Model = model.stories[0] ;
// NSLog(@"%d",self.Model == nil) ;
NSLog(@"%@",self.Model.title) ;
NSDictionary* dict = [[NSDictionary alloc] init] ;
dict = [model toDictionary];
NSLog(@"%@", dict[@"stories"][0][@"title"]) ;
上面那段代码有个要注意的点,即直接对获取到的model访问他的属性会直接使程序奔溃,但具体原因不是特别清楚(主要是不知道为什么奔溃);
#import “ViewController.h”
#import
//#import “AFNetworking.h”
#import “TestModel.h”
#import “Manager.h”
@interface ViewController ()
@end
@implementation ViewController
(void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
// NSString* jsonstr = @“https://news-at.zhihu.com/api/4/news/latest” ;
// jsonstr = [jsonstr stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]] ;
// NSURL* testurl = [NSURL URLWithString:jsonstr] ;
// NSURLRequest* resquest = [NSURLRequest requestWithURL:testurl] ;
AFURLSessionManager* sessionmanager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]] ;
// NSURLSession* session = [NSURLSession sharedSession] ;
// NSURLSessionTask* sessiontask = [session dataTaskWithRequest:resquest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
// if (error) {
// NSLog(@“Error: %@”,error) ;
// } else {
// TestModel* model = [[TestModel alloc] initWithData:data error:nil] ;
// NSLog(@“%@”,model) ;
self.model01 = model.stories[1] ;
// NSLog(@“%@”,model.stories[0]) ;
//
// self.Model = model.stories[0] ;
NSLog(@“%d”,self.Model == nil) ;
// NSLog(@“%@”,self.Model.title) ;
// NSDictionary* dict = [[NSDictionary alloc] init] ;
// dict = [model toDictionary];
// NSLog(@“%@”, dict[@“stories”][0][@“title”]) ;
//
// }
// }] ;
//
// [sessiontask resume] ;
//
//
[self getModel] ;
[self postnet] ;
[self getnet] ;
[self postnet01] ;
}
(void)getModel {
[[Manager shareSingleton] NetWorkGetWithData:^(TestModel * _Nullable mainModel) {
NSDictionary* dict01 = [[NSDictionary alloc] init] ;
dict01 = [mainModel toDictionary] ;
NSLog(@“%@”,dict01) ;
NSLog(@“%@”,dict01[@“stories”][1][@“title”]) ;
} andError:^(NSError * _Nullable error) {
NSLog(@“%@”,error) ;
}] ;
}
(void)getnet {
AFHTTPSessionManager* manager = [AFHTTPSessionManager manager] ;
[manager GET:@“https://news-at.zhihu.com/api/4/news/before/20221023” parameters:nil headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@“get成功 %@”,responseObject[@“date”]) ;
if ([responseObject isKindOfClass:[NSData class]]) {
self.getdict = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableLeaves error:nil] ;
NSLog(@“%@”,self.getdict) ;
} else {
NSLog(@“NO”) ;
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@“Error : %@”,error) ;
}] ;
}
(void)postnet {
AFHTTPSessionManager* manager = [AFHTTPSessionManager manager] ;
[self.postdict setObject:@“Viper” forKey:@“userName”];
[self.postdict setObject:@“Viper333” forKey:@“passWord”];
[manager POST:@“https://news-at.zhihu.com/api/4/news/before/20221023” parameters:self.postdict headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@“error : %@”,error) ;
}] ;
}
(void)postnet01 {
AFHTTPSessionManager* manager = [AFHTTPSessionManager manager] ;
self.postdict = [[NSMutableDictionary alloc] init] ;
[self.postdict setObject:@“Viper” forKey:@“userName”];
[self.postdict setObject:@“Viper333” forKey:@“passWord”];
[manager POST:@“https://news-at.zhihu.com/api/4/news/before/20221023” parameters:self.postdict headers:nil constructingBodyWithBlock:^(id _Nonnull formData) {
UIImage* image = [UIImage imageNamed:@“xue.png”] ;
NSData* imagedata = UIImagePNGRepresentation(image);
[formData appendPartWithFileData:imagedata name:@“file” fileName:@“ImageUp.png” mimeType:@“image/png”] ;
} progress:^(NSProgress * _Nonnull uploadProgress) {
NSLog(@“%f”,1.0 * uploadProgress.completedUnitCount / uploadProgress.totalUnitCount) ;
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@“success”) ;
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@“failure”) ;
}] ;
}
@end
上面还涉及到了AFNetworking的使用,下一篇博客写这个