zoukankan      html  css  js  c++  java
  • 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
                )
                
            }
        }
        
    }
    

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

  • 相关阅读:
    ES6中的class的详解
    JavaSrcipt中字符串和数组容易搞混的操作
    ES6中的数据结构Map的理解和描述
    ES6中新增数据结构Set的理解和用法详情描述
    ES6中的Promise的用法总结
    JS中的async/await的用法和理解
    字节跳动、拼多多前端面经
    前端项目优化 -Web 开发常用优化方案、Vue & React 项目优化
    记几个 DOM 操作技巧
    JavaScript 面试题
  • 原文地址:https://www.cnblogs.com/mtystar/p/6035474.html
Copyright © 2011-2022 走看看