【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实现的网络请求

相关推荐
用户091 天前
SwiftUI Charts 函数绘图完全指南
ios·swiftui·swift
YungFan1 天前
iOS26适配指南之UIColor
ios·swift
权咚2 天前
阿权的开发经验小集
git·ios·xcode
用户092 天前
TipKit与CloudKit同步完全指南
ios·swift
小溪彼岸2 天前
macOS自带截图命令ScreenCapture
macos
法的空间2 天前
Flutter JsonToDart 支持 JsonSchema
android·flutter·ios
2501_915918412 天前
iOS 上架全流程指南 iOS 应用发布步骤、App Store 上架流程、uni-app 打包上传 ipa 与审核实战经验分享
android·ios·小程序·uni-app·cocoa·iphone·webview
TESmart碲视2 天前
Mac 真正多显示器支持:TESmart USB-C KVM(搭载 DisplayLink 技术)如何实现
macos·计算机外设·电脑
00后程序员张2 天前
iOS App 混淆与加固对比 源码混淆与ipa文件混淆的区别、iOS代码保护与应用安全场景最佳实践
android·安全·ios·小程序·uni-app·iphone·webview
Magnetic_h2 天前
【iOS】设计模式复习
笔记·学习·ios·设计模式·objective-c·cocoa