IOS 使用Block二次封装AFNetworking 3.0详解

yizhihongxing

IOS 使用Block二次封装AFNetworking 3.0详解

1. 前言

AFNetworking 是 iOS 开发中常用的网络请求库,其基于 NSURLConnectionNSURLSession,提供了更加简单方便的接口,使得开发者可以方便地进行网络请求。

但是,AFNetworking 中的回调方式为传统的代理方法,不够便捷。为此,我们可以进行二次封装,使用 Block 作为网络请求结果的回调方式,在开发中更为方便。

本文将详细讲解如何使用 Block 二次封装 AFNetworking,并提供示例说明。

2. 封装过程

2.1 创建网络请求类

先创建一个网络请求类 NetRequest。这个类提供网络请求的基本功能,包括 GET 请求、POST 请求、上传文件等主要的请求功能。

这个网络请求类可以使用单例模式,保证全局只有一个实例。

@interface NetRequest : NSObject

+ (instancetype)getInstance;

- (void)requestWithMethod:(NSString *)method
                      url:(NSString *)url
               parameters:(NSDictionary *)parameters
                  success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                  failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure;

@end

2.2 实现网络请求类

在实现网络请求类时,我们需要使用 AFNetworking 中提供的 AFHTTPSessionManager 类。我们可以将这个类的实例作为属性加入到我们的网络请求类中。

@interface NetRequest()

@property (nonatomic, strong) AFHTTPSessionManager *manager;

@end

@implementation NetRequest

+ (instancetype)getInstance {
    static NetRequest *request = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        request = [[NetRequest alloc] init];
    });
    return request;
}

- (instancetype)init {
    if (self = [super init]) {
        _manager = [AFHTTPSessionManager manager];
        _manager.requestSerializer = [AFJSONRequestSerializer serializer];
        _manager.responseSerializer = [AFJSONResponseSerializer serializer];
    }
    return self;
}

- (void)requestWithMethod:(NSString *)method
                      url:(NSString *)url
               parameters:(NSDictionary *)parameters
                  success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                  failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure {
    if ([method isEqualToString:@"GET"]) {
        [self.manager GET:url
               parameters:parameters
                  headers:nil
                 progress:nil
                  success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            if (success) {
                success(task, responseObject);
            }
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            if (failure) {
                failure(task, error);
            }
        }];
    } else if ([method isEqualToString:@"POST"]) {
        [self.manager POST:url
                parameters:parameters
                   headers:nil
                  progress:nil
                   success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            if (success) {
                success(task, responseObject);
            }
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            if (failure) {
                failure(task, error);
            }
        }];
    }
}

@end

其中:

  • GET 请求使用 GET 方法,同时对应的成功和失败的回调均使用传入的 successfailure 参数来获取。
  • POST 请求使用 POST 方法,同时对应的成功和失败的回调均使用传入的 successfailure 参数来获取。

NetRequest 类的实现完成后,我们就可以使用这个类来进行网络请求了。

2.3 进一步封装

如果我们需要在网络请求中添加其他的功能,例如数据缓存,请求重试等,都可以在 NetRequest 类中进一步实现。

例如:实现一个添加缓存功能的网络请求方法

/**
 * GET 请求,支持缓存
 * @param url 请求 URL
 * @param parameters 请求参数
 * @param cache 过期时间,单位为秒,-1 表示永不过期,0 表示不使用缓存,默认为 -1。
 * @param success 请求成功回调
 * @param failure 请求失败回调
 */
- (void) getWithUrl:(NSString *)url
         parameters:(NSDictionary *)parameters
               cache:(NSTimeInterval)cache
            success:(void (^)(NSURLSessionDataTask *, id))success
            failure:(void (^)(NSURLSessionDataTask *, NSError *))failure {
    if (cache > 0) {
        // 从缓存中获取数据
        id responseObject = [CacheManager cacheForKey:url];
        if (responseObject) {
            if (success) {
                success(nil, responseObject);
            }
            return;
        }
    }

    // 没有从缓存中获取到数据,进行网络请求
    [self getWithUrl:url parameters:parameters success:^(NSURLSessionDataTask *task, id responseObject) {
        if (cache > 0) {
            // 将数据保存在缓存中
            [CacheManager setCache:responseObject forKey:url expireTime:cache];
        }
        if (success) {
            success(task, responseObject);
        }
    } failure:^(NSURLSessionDataTask *task, NSError *error) {
        if (failure) {
            failure(task, error);
        }
    }];
}

其中,如果 cache 参数大于 0,我们会先从缓存中获取数据,如果缓存中有数据,就直接返回,并调用成功回调。如果没有缓存数据,就进行网络请求。

3. 示例说明

下面是两个示例,演示如何使用封装好的 NetRequest 类进行网络请求。

示例1:GET 请求

NSDictionary *params = @{@"key1": @"value1", @"key2": @"value2"};
[[NetRequest getInstance] requestWithMethod:@"GET"
                                        url:@"http://httpbin.org/get"
                                 parameters:params
                                    success:^(NSURLSessionDataTask *task, id responseObject) {
        NSLog(@"%@", responseObject);
    }
                                    failure:^(NSURLSessionDataTask *task, NSError *error) {
        NSLog(@"%@", error);
    }];

这个请求会向 httpbin.org 发送一个 GET 请求,并将 params 中的参数附加在 URL 后面,请求成功回调中会打印出服务端返回的数据。

示例2:下载文件

NSString *url = @"http://httpbin.org/image/jpeg";
NSURLSessionDownloadTask *task = [[NetRequest getInstance].manager downloadTaskWithURL:[NSURL URLWithString:url] completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    if (error) {
        NSLog(@"Download Error: %@", error);
    } else {
        NSString *documentsDirectoryPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
        NSString *fileUrl = [documentsDirectoryPath stringByAppendingPathComponent:@"image.jpeg"];
        [[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:fileUrl] error:nil];
    }
}];
[task resume];

这个请求会向 httpbin.org 发送一个下载图片的请求,请求成功后会将图片下载到应用的 document 目录中。

4. 总结

以上就是使用 Block 二次封装 AFNetworking 3.0 的完整攻略。我们可以将这个封装好的网络请求类作为一个通用的工具类,方便项目中的其他模块使用。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:IOS 使用Block二次封装AFNetworking 3.0详解 - Python技术站

(0)
上一篇 2023年6月25日
下一篇 2023年6月25日

相关文章

  • Javascript基础教程之变量

    JavaScript基础教程之变量 什么是变量? 在JavaScript中,变量是用于存储数据的容器。它们可以存储各种类型的数据,例如数字、字符串、布尔值等。变量还可以在程序中被修改和访问。 声明变量 在JavaScript中,我们使用var、let或const关键字来声明变量。这些关键字有不同的作用范围和行为。 使用var声明变量 var是在ES5中引入的…

    other 2023年8月9日
    00
  • 你的电脑将在一分钟后自动重启如何解决 win8自动重启解决办法

    问题背景 Win8系统中,电脑会出现自动重启的情况,弹出提示框显示“你的电脑将在一分钟后自动重启”。这给用户带来了极大的不便,甚至导致数据丢失。那么如何解决Win8系统的自动重启问题呢?本文将为您提供完整攻略。 解决方法 方法一:取消自动重启 按下Win+R组合键,调出运行窗口,输入“gpedit.msc”并回车。 在“本地组策略编辑器”窗口中依次展开“计算…

    other 2023年6月27日
    00
  • grafana安装及使用教程详解

    首先,需要说明的是grafana是一个流行的开源数据可视化工具,可以帮助用户将不同数据源的数据可视化展示。下面是grafana安装及使用教程详解。 安装grafana 下载grafana: 官网下载链接(https://grafana.com/grafana/download) 解压下载的zip文件: unzip grafana-x.x.x.zip 进入gr…

    other 2023年6月27日
    00
  • Go语言中map使用和并发安全详解

    Go语言中map使用和并发安全详解 概述 在Go语言中,map是一种集合类型,它可以关联一个键和一个值。map是一种引用类型,可以使用 make 函数来创建。map 的底层实现是 hash 表,因此 map 的键是无序的,但是在迭代过程中,Go语言会自动对其进行排序。 map 的基本使用方法是:使用键访问值,如果键不存在,则会返回初始值。map 与 slic…

    other 2023年6月26日
    00
  • C++音乐播放按钮的封装过程详解

    C++音乐播放按钮的封装过程详解 在本篇攻略中,我们将会详细讲解如何使用C++对音乐播放按钮进行封装。这个过程中,我们需要用到以下步骤: 确定需求和按钮设计 编写头文件和源文件 在主函数中实例化 进行功能测试 确定需求和按钮设计 在进行封装之前,首先需要确定我们的需求和按钮设计。在这个例子中,我们需要做出一个简单的音乐播放按钮,它可以控制音乐的播放、暂停和停…

    other 2023年6月25日
    00
  • Java面向对象之内部类案例讲解

    下面是详细讲解“Java面向对象之内部类案例讲解”的完整攻略。 什么是内部类? 内部类是在类内部定义的类,也就是说它是一个嵌套在其他类中的类。内部类可以直接访问包含它的外部类的所有成员,包括私有成员。Java中主要有四种内部类,分别是静态内部类、非静态内部类(成员内部类)、局部内部类和匿名内部类。 静态内部类 静态内部类也叫作嵌套类,它是被static修饰的…

    other 2023年6月27日
    00
  • python递归实现链表快速倒转

    在 Python 中,可以使用递归算法实现链表快速倒转。具体步骤如下: 定义一个递归函数 reverseLinkedList,该函数接受一个链表头节点作为参数。 在函数体内,首先判断当前链表是否只有一个节点或者为空。如果是,直接返回该节点或者 None。 如果当前链表不是一个节点,递归调用 reverseLinkedList 函数并传入链表的下一个节点作为参…

    other 2023年6月27日
    00
  • vue cli4下环境变量和模式示例详解

    Vue-cli4环境变量和模式示例详解 环境变量介绍 在我们日常开发中,我们经常会需要在单个代码库中支持多个部署环境,比如开发环境、测试环境、预发环境和生产环境。而在不同的部署环境下,我们经常需要对不同环境进行不同的配置,比如服务器地址,接口路径等。Vue-cli4提供了灵活的方式,使我们能够对这些不同的环境进行不同的配置。 简单来说,Vue-cli4 中的…

    other 2023年6月27日
    00
合作推广
合作推广
分享本页
返回顶部