Swift -- 对AFN框架的封装

Swift -- 对AFN框架的封装

一.封装AFN的目的

  • 简单的说: 解耦

  • 日常工作中,我们一般都不会去直接使用AFNetWorking来直接发送网络请求,因为耦合性太强,假设有多个控制器都使用AFN发送请求,那么假设有一天AFN框架的作者不更新了,到时我们需要改动的地方太多太多~

  • 所以这里我们要自己来封装AFN

二.封装之前准备工作:

  • 利用cocoapods集成AFN框架

三.封装AFN的方式

  • 封装AFN有两种方法:
    • 工具类,继承NSObject
    • 继承AFHTTPSessionManager

四.封装实现

第一种, 继承NSObject封装AFN

实现代码如下:

import UIKit
import AFNetworking

// 请求类型
enum RequestType
{
    case Get
    case Post
}

class MTYNetWorking: NSObject {
    
    // 单例
    static let shareInstance = MTYNetWorking()
    
    // 懒加载 - 方式1: 单纯的懒加载
    lazy var mgr = AFHTTPSessionManager()
    
    /* 懒加载 - 方式2: 可以对请求管理者做些初始化的操作
    lazy var mgr = {
        
        // 可以做些初始化的操作
        return $0
        
    }(AFHTTPSessionManager())
    */
    
    /// 对外提供的网络请求接口
    ///
    /// - Parameters:
    ///   - requestType: 发送请求的类型,是个枚举
    ///   - url: 请求路径
    ///   - parameters: 请求参数,字典类型
    ///   - resultBlock: 请求结果
    func request(requestType:RequestType,
                 url:String,
                 parameters:[String: Any],
                 resultBlock:@escaping (_ response: [String: Any]?,_ error: String?) -> ())
    {
        
        // 请求成功的闭包
        let successBlock = { (task: URLSessionDataTask, response: Any?) in
            // 拿到结果
            resultBlock((response as? [String: Any])!, nil)
        }
        
        // 请求失败的闭包
        let failuerBlock = { (task: URLSessionDataTask?, error: Error) in
            // 拿到结果
            resultBlock(nil, error.localizedDescription)
        }
        
        // 发送异步 Get请求
        if requestType == .Get {
            mgr.get (
                url,
                parameters: parameters,
                progress: nil,
                success: successBlock,
                failure: failuerBlock
            )

        // 发送异步 Post请求
        }else if requestType == .Post
        {
            mgr.post (
                url,
                parameters: parameters,
                progress: nil,
                success: successBlock,
                failure: failuerBlock
            )
            
        }
   
    }

}

封装时的注意点:

1.单例:

因为上面的封装使用的是对象方法,外界模块在使用我们这个工具类时每次都会创建一个对象,来调用接口,然后他们并不会被释放,所以为了保证整个内存里面只存在一个对象,要使用单例.

// static 保证内存中只有1份
// let 常量,不可以被改变
// 因为shareInstance这个属性是依附于类(MTYNetWorking)的,所以只有一份
static let shareInstance = MTYNetWorking()

2.懒加载请求管理者的两种方式

3.为什么使用闭包来传值

  • 设计这个接口的最终目的,就是拿到请求后的返回结果.但是我们不能把这个结果放到方法的返回值处,这样外界在调用的时候要么立即拿到这个结果,否则就会等待这个结果,也就是发送了一个同步的请求,这样会阻塞主线程,影响用户的体验,所以一般使用逃逸闭包来传值
  • AFN框架的success和failure后面的闭包的目的就是要告诉我们请求结果的,无论是请求成功还是失败
  • 而我们设计这个接口的目的就是通过闭包来告诉外面的结果

第二种, 继承AFHTTPSessionManager封装AFN

代码实现

import UIKit
import AFNetworking

// 请求类型
enum RequestType2
{
    case Get
    case Post
}

class MTYNetWorkingTool: AFHTTPSessionManager {

    // 单例
    static let shareInstance = MTYNetWorkingTool()
    
    func request(type: RequestType2,
                 url: String,
                 parameters: [String: Any],
                 resultBlock:@escaping ((_ response:[String: Any]?, _ error: Error?) ->())) {
        
        // 成功的闭包
        let successBlock = { (task: URLSessionDataTask, response: Any?) in
            
            resultBlock(response as? [String: Any], nil)
        }
        
        // 失败的闭包
        let failureBlock = { (task: URLSessionDataTask?, error: Error) in
            
            resultBlock(nil, error)
        }
        
        // Get 请求
        if type == .Get {
            
          get(
            url,
            parameters: parameters,
            progress: nil,
            success: successBlock,
            failure: failureBlock
            )
        // Post请求
        }else if type == .Post {
        
          post(
            url,
            parameters: parameters,
            progress: nil,
            success: successBlock,
            failure: failureBlock
            )
            
        }
    }
    
}

如有错误之处,请指正!谢谢~

posted @ 2016-11-06 15:40  Oo11  阅读(879)  评论(0编辑  收藏  举报