【iOS】使用单例封装通过AFNetworking实现的网络请求

这里写目录标题


前言

先前在天气预报中笔者用到了Foundation框架中原生的网络请求类NSURLSession,我们先来看一下我们通过NSURLSession请求网络数据的示例:

objectivec 复制代码
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
    request.HTTPMethod = @"GET";
    [request setValue:@"application/json" forHTTPHeaderField:@"Conten-Type"];
    
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if(error){
            NSLog(@"error = %@",error);
        }else{
            NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
            NSLog(@"dic = %@",dic);
        }
    }];
    [task resume];

接下来我们再看一下通过AFNetworking如何进行网络请求:

objectivec 复制代码
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    [manager GET:url parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"responseObject = %@",responseObject);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if (error) {
            NSLog(@"error = %@",error);
        }
    }];

这样一对比,很显然通过AFNetworking实现网络请求需要的代码量更少

接下来笔者会通过示例具体讲解使用单例封装通过AFNetworking实现的网络请求

单例封装网络请求

在介绍单例封装网络请求的用法前,我们先来讲解一下我们为什么要使用单例来封装网络请求:

在先前的天气预报中,因为有许多个页面,每个页面中都需要从网络中请求数据,因此笔者就创建多个对象来请求不同的网络数据,但是这无疑浪费了内存,如果有一个单例专门负责进行网络请求,就不会出现这样的问题,

同时将网络请求逻辑封装到一个单例类中,这个类负责创建、管理和发送网络请求。这样,你可以将网络请求的相关代码集中在一个地方,以提高代码的可维护性和可读性。

接下来笔者将通过示例讲解这方面的知识:

1. 首先创建一个继承于NSObject的单例类,笔者这里以Manager对单例类进行命名,然后声明并实现单例类的初始化方法

.h文件:

.m文件:

objectivec 复制代码
//创建一个单例
static Manager *managerSington = nil;

@implementation Manager

+ (instancetype)shareManager {
    if (!managerSington) {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            managerSington = [[Manager alloc] init];
        });
    }
    return managerSington;
}

在这里创建单例笔者使用了GCD,GCD在此的作用是确保代码块只被执行一次。这是线程安全的,即使在多线程环境下也不会出现问题。

static dispatch_once_t onceToken;:这是用于确保代码块只执行一次的GCD的dispatch_once_t变量。

dispatch_once(&onceToken, ^{ ... }):这是GCD的dispatch_once函数,它接受一个 dispatch_once_t 变量和一个代码块作为参数。它确保代码块中的代码只会在第一次调用时执行,以后的调用会被忽略。

2.实现完单例的创建方法后我们即可通过AFNetworking中的GET方法进行网络请求

objectivec 复制代码
- (void)NetWorkGetWithData:(id)TestModelBolck andError:(id)errorBlock {

    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    
    NSString *url = @"https://news-at.zhihu.com/api/4/version/ios/2.3.0";
    
    [manager GET:url parameters:nil headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
    
        TestModel2 *testModel = [[TestModel2 alloc] initWithDictionary:responseObject error:nil];
        
        mainModelBolck(testModel);
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
    
        NSLog(@"Error: %@", error);
        
    }];
}

我们接下来分析一下GET方法的源码对其进行解析:

objectivec 复制代码
- (NSURLSessionDataTask *)GET:(NSString *)URLString
                   parameters:(nullable id)parameters
                      headers:(nullable NSDictionary <NSString *, NSString *> *)headers
                     progress:(nullable void (^)(NSProgress * _Nonnull))downloadProgress
                      success:(nullable void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success
                      failure:(nullable void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure
{
    
    NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"GET"
                                                        URLString:URLString
                                                       parameters:parameters
                                                          headers:headers
                                                   uploadProgress:nil
                                                 downloadProgress:downloadProgress
                                                          success:success
                                                          failure:failure];
    
    [dataTask resume];
    
    return dataTask;
}

笔者在这里解释一下各个参数的含义

URLString(NSString类型):表示要发送GET请求的URL字符串,即请求的目标地址。
parameters(可选的id类型):包含GET请求的参数,这些参数会附加到URL字符串中,以便服务器可以根据这些参数返回相应的数据。它通常是一个NSDictionary或其他数据结构,其中包含键值对,表示请求参数。
headers(可选的NSDictionary类型):包含HTTP请求头的字典。HTTP请求头通常包含与请求相关的信息,例如授权令牌、用户代理、接受的数据类型等。这里的参数允许你自定义请求头。
downloadProgress(可选的NSProgress类型块):一个块对象,用于跟踪下载进度。这个块会在下载数据时被调用,可以用来更新UI或记录下载进度等。
success(可选的块):一个成功回调块,当请求成功完成时会被调用。这个块通常接受两个参数,第一个参数是包含响应数据的NSURLSessionDataTask对象,第二个参数是响应数据,通常是一个NSDictionary或其他数据结构。
failure(可选的块):一个失败回调块,当请求失败时会被调用。这个块通常接受两个参数,第一个参数是包含请求任务信息的NSURLSessionDataTask对象,第二个参数是一个NSError对象,包含了关于请求失败的信息。

在这个方法内部,首先通过调用dataTaskWithHTTPMethod:URLString:parameters:headers:uploadProgress:downloadProgress:success:failure:方法创建一个NSURLSessionDataTask对象,然后使用resume方法开始执行这个任务(发送GET请求),最后返回该任务对象,以便调用者可以对任务进行进一步操作或取消。

关于AFNetworking的源码以后还会深度学习,在GET方法中需要注意的是当我们请求成功后返回的id _Nullable responseObject,这个参数是响应数据,通常是一个NSDictionary或其他数据结构。我们通过将responseObject赋值给我们的JSONModel对象即可得到我们从网络中请求到的数据

当我们成功请求到数据并将其放入我们的对象后,我们通过Block传值将其对象传递给到我们的其他文件中

objectivec 复制代码
typedef void (^TestModelBlock) (TestModel2 *model);
typedef void (^TestModelBlockElse) (TestModel3 *model);

然后在实现文件中进行代码块的传递:

objectivec 复制代码
    [manager GET:url parameters:nil headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
    
        TestModel2 *testModel = [[TestModel2 alloc] initWithDictionary:responseObject error:nil];
        
        mainModelBolck(testModel);
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
    
        NSLog(@"Error: %@", error);
        
    }];

3.在Controller文件中创建单例并执行网络请求的方法

objectivec 复制代码
    [[Manager shareManager] NetWorkGetWithData:^(TestModel2 *TestModelBolck) {
        NSLog(@"%@",TestModelBolck);
        NSLog(@"请求成功");
    } andError:^(NSError * _Nullable error) {
        NSLog(@"失败");
    }];

综合以上这三步我们就成功使用单例封装通过AFNetworking实现的网络请求

相关推荐
1telescope15 小时前
MacBook 安装 nvm 管理 Node.js 多版本教程
macos·node.js
1telescope16 小时前
MacBook 安装 Oh My Zsh 完整教程
macos·mac
蜜汁小强16 小时前
macOS 上的git代理配置在哪里
git·macos·代理模式·proxy模式
蜜汁小强17 小时前
macOS 上升级到 python 3.12
开发语言·python·macos
上天_去_做颗惺星 EVE_BLUE18 小时前
Android设备与Mac/Docker全连接指南:有线到无线的完整方案
android·linux·macos·adb·docker·容器·安卓
小码过河.18 小时前
设计模式——单例模式
单例模式·设计模式
2501_9160088918 小时前
iOS开发APP上架全流程解析:从开发到App Store的完整指南
android·ios·小程序·https·uni-app·iphone·webview
goodmao18 小时前
【macOS】【磁盘空间整理】查看大文件夹
macos
七夜zippoe19 小时前
Cython终极性能优化指南:从Python到C++的混合编程实战
c++·python·macos·cython·类型系统·内存视图
2501_915909061 天前
Charles 抓不到包怎么办?iOS 调试过程中如何判断请求路径
android·ios·小程序·https·uni-app·iphone·webview