• 【iOS】——用单例类封装网络请求



    一、JSONModel

    1.JSONModel的简单介绍

    JSONModel一个第三方库,这个库用来将网络请求到的JSON格式的数据转化成Foundation框架下的Model类的属性,这样我们就可以直接通过访问Model类的属性来访问网络请求到的数据。

    2.JSONModel的使用

    要使用JSONModel库首先需要通过CocoaPods下载第三方库到目标文件中。接着在文件中创建一个Model类并且继承于JSONModel类。根据网络请求的JSON格式数据确定创建的类和属性。
    例如JSON数据格式如下:

    请添加图片描述

    请添加图片描述

    那么就需要在Model类中声明接收数据的协议并实现继承于JSONModel的类,这里我声明了storiesModel和top_StoriesModel两个协议并实现继承于JSONModel类的storiesModel和top_StoriesModel类来实现接收网络请求的数据。

    GetModel.h

    @protocol storiesModel
    
    @end
    
    @protocol top_StoriesModel
    
    @end
    #import <JSONModel/JSONModel.h>
    #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;
    
    @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 GetModel : JSONModel
    @property (nonatomic, copy) NSString* date;
    @property (nonatomic, copy) NSArray<storiesModel>* stories;
    @property (nonatomic, copy) NSArray<top_StoriesModel>* top_stories;
    @end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    GetModel.m

    #import "GetModel.h"
    
    @implementation GetModel
    
    + (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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    在GetModel.m中使用+ (BOOL)propertyIsOptional:(NSString *)propertyName方法来指定模型类中的属性是否为可选的。默认情况下,所有的属性都被认为是必需的,也就是说在 JSON 数据中必须存在对应的键值。但是,也可以重写该方法并返回 YES 或 NO 来指定特定属性是否可以在 JSON 数据中不出现。

    二、单例类和Block传值

    在iOS开发中,一般要通过一些管理类来封装特定的属性或成员变量,这时就可以用单例类来实现。原因是单例类在程序运行时只创建一次,当程序结束后才被销毁,这样会提高运行效率并且降低代码风险,但是实现单例类时又需要考虑线程安全问题,所以这里用到GCD写法来创建单例类。

    在Manager.h中声明类方法

    +(instancetype)sharedSingleton;
    
    • 1

    在Manager.m中定义一个局部全局变量并实现接口部分声明的类方法。

    static Manager* manager = nil;
    + (instancetype)sharedSingleton {
        if (manager == nil) {
            static dispatch_once_t onceToken;
            dispatch_once(&onceToken, ^{
                manager = [[Manager alloc] init];
            });
        }
        return manager;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    dispatch_ once _t: 使用 dispatch_once 方法能保证某段代码在程序运行过程中只被执行 1 次,并且即使在多线程的环境下,dispatch _once也可以保证线程安全。

    在单例类中要封装网络请求并实现传值,因此需要用到Block传值

    在Manager.h中定义两个Block块来接收请求到的数据并声明一个方法来封装网络请求

    typedef void (^GetModelBlock)(GetModel * _Nullable mainModel);
    typedef void (^ErrorBlock)(NSError * _Nullable error);
    - (void)NetWorkGetWithData:(GetModelBlock)mainModelBlock andError:(ErrorBlock)errorBlock;
    
    • 1
    • 2
    • 3

    在Manager.m中实现该方法

    - (void)NetWorkGetWithData:(GetModelBlock)mainModelBolck andError:(ErrorBlock)errorBlock {
    	//创建一个网络请求
        NSString *json = @"https://news-at.zhihu.com/api/4/news/latest";
        json = [json stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
        NSURL *netWorkDataURL = [NSURL URLWithString:json];
        NSURLRequest *netWorkDataRequest = [NSURLRequest requestWithURL:netWorkDataURL];
        //创建请求会话
        NSURLSession *netWorkDataSession = [NSURLSession sharedSession];
        //根据会话创建任务
        NSURLSessionDataTask *netWorkDataTask = [netWorkDataSession dataTaskWithRequest:netWorkDataRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            if (error == nil) {
                GetModel *allGetData = [[GetModel alloc] initWithData:data error:nil];
                //使用Block传值
                mainModelBolck(allGetData);
            } else {
                errorBlock(error);
            }
        }];
        //启动任务
        [netWorkDataTask resume];
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在主函数中

     [[Manager sharedSingleton] NetWorkGetWithData:^(GetModel * _Nullable mainModel) {
            NSLog(@"%@", mainModel.stories[1]);
            NSLog(@"获取成功");
        } andError:^(NSError * _Nullable error) {
            NSLog(@"请求失败");
        }];
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    运行结果如下:

    请添加图片描述


  • 相关阅读:
    前后端数据交互与HTTP协议
    传输层 用户数据报协议(UDP)
    数据分析回头看2——重复值检查/元素替换/异常值筛选
    C语言进阶C++知识点补充(一)
    黑客技术(网络安全)自学2024
    抖音小店运营计划书怎么写?运营技巧及入住条件资料
    【医学】模拟骨料填料发生器附matlab代码
    【OpenCV 例程200篇】219. 添加数字水印(盲水印)
    服装工业新消费·PLM
    G2plot 面积图Area更新空数据,页面渲染不彻底
  • 原文地址:https://blog.csdn.net/m0_73974920/article/details/133845695