Swift 中 POP 思想的使用

1,309 阅读6分钟
1.什么是  POP  ? 
        这个在2015年的 WWDC上有提过,所以作为 iOS开发者每年的WWDC 应该是必看的!       2.有什么用?         在开发过程中,用到的网络请求、数据库存储等。这些都可以用到POP思想。准确的来说就是便于解耦,减少代码的重复性。
        在之前的开发过程中我一直用OC开发的,直到我了解到POP思想后就用2周的时间把公司的开发语言从 OC 切换到 Swift ,一路上也是没少踩坑!
        个人觉得换一门语言不应该看别人用了就随大流,要是自己真正的认识到了这么语言有其它语言不可替代的思想。在我面试的过程中我就问过一些从事Swift语言的开发者对公司用swift的原因,他们都说是看别人在用......
      
  • 进入主题

        用POP进行网络请求是一个非常不错的选择,当然已经有许多成熟的库利用 Alamofire   进一步封装,以POP的思想进行网络请求。虽然不应该重复造轮子,但是对于一些原理我们还是应该学习的。

  1. 首先建立一个项目,并在项目中集成:

      首先并不是所有的网络请求都是这样的,而我以往的开发过程中都是一些金融类且规模较大的App,所以都毫无疑问的集成了这些。对一些轻量级的网络请求用系统的就足够了。这里我用到了一个网络请求与JSON解析的库。这些都是非常不错的开源库!对其原理都是应该非常了解的。

  • 建立一个网络请求的协议类
  1. 对于一个网络请求请求 URL 是必不可少。
            但是在项目开发过程中 域名可能用到的可能不止一个,许多事情都是能按照理想的发展固然很好。而有时候事情的出现应该去着手去解决而不是一味着抱怨!
            在我开发过程中后台提供了三个域名,我就很费解! 沟通后发现不能改,因为与前端共用一套......,而当初为前端做接口的时候没有考虑到App。所以在程序框架搭建的时候就应该考虑到这些问题!
                  对于一个网络请求接口也要做专门的如下处理:
import Foundation

struct Api {
    static let host = "http://api.isanjie.com/"
    
    static func map(path: String) -> String {
        return host + path
    }
    
    static var goodsParticularsURL: String {
        return map(path: "goods/getgoods")
    }
    ///  ...... 接着继续其他接口的书写......
}
这样在调用相应接口的时候,可以直接调用   Api.goodsParticularsURL 当然你可以写的更简洁些...
接下来我们以定义协议的方式进行网络请求✍️

  1. 首先一个基本的网络请求有以下参数:
  • 请求路径  path
  • 请求方式     
                    OPTIONS

                  GET

                  HEAD

                  POST

                  PUT

                    ……

      在这里  Alamofire 内 HTTPMethod 解决了这个问题

  • 请求体
            这里请求体以字典的形式  [ String: AnyObject]

    • 对请求的结果进行数据处理的函数以一个协议的形式进行 , 对于协议可以充分利用Swift 协议扩展来解决重复性比较大的问题

          protocol Decodable {

              static func parse(anyData: Any) -> Self?

          }

    • 网络请求也是充分利用 Swift 协议的特点

             用到 泛型 <T: Reques>

    
    protocol SenderRequest {
        func send(_ p: T, analysis: @escaping (T.Analysis?) -> Void)
    }
    
    • 然后就用Alamofire 网络请求,但是对网络请求下的结果给另一函数进行处理,如下以上文字的代码实现 :
    
     import Foundation
    import Alamofire
    
    protocol Request {
        
        var path: String { get }
        
        var method: HTTPMethod { get }
        
        var parameter: [String: AnyObject] { get }
        
        associatedtype Analysis: Decodable
    }
    
    protocol Decodable {
        static func parse(anyData: Any) -> Self?
    }
    
    protocol SenderRequest {
        func send(_ p: T, analysis: @escaping (T.Analysis?) -> Void)
    }
    
    struct SessionRequestSender: SenderRequest {
        func send(_ p: T, analysis: @escaping (T.Analysis?) -> Void) {
            
            Alamofire.request(p.path, method: p.method, parameters: p.parameter).responseJSON { (response) in
                switch response.result {
                case .success:
                    if let anyData = response.result.value, let result = T.Analysis.parse(anyData: anyData) {
                        DispatchQueue.main.async {
                            analysis(result)
                        }
                    }
                case .failure(_):
                    break
                }
            }
        }
    }
    
    • 对网络请求的发起继承上面的协议即可
    网络的发起以 实现协议的方式进行
    这是我在实际开发过程中对商品详情的接口定义 ✍️ 这里只用到一个参数  goodsId 就用到了一个,如果有多个可以继续书写
    
     extension ParticularsAnalysis: Decodable {
        static func parse(anyData: Any) -> ParticularsAnalysis? {
            return ParticularsAnalysis(anyData: anyData)
        }
    }
    struct ParticularsAnalysis {
        
        var message: Bool
        var tempData: Any
        
        init?(anyData: Any) {
            
            let obj = JSON(anyData)
            
            guard let name = obj["errno"].int else {
                self.message = false
                return nil
            }
            
            if name == 2000 {
                self.message = true
                self.tempData = anyData
            } else {
                self.message = false
                self.tempData = anyData
                
            }
        }
    }
    
    同样是利用Swift 协议的扩展,进行解析函数的扩展

    有网络的发起就有对数据的解析,这里定义一个 结构体对网络的解析  message 是一个请求状态值,这里可以定义不同的参数   anyData 是网络请求的结果数据,用Alamofire请求的数据是 Any 型,这里定义的参数都会直接以闭包的形式返回给函数的发起地方,这个地方只是对数据拆解的工厂
    • 以下是完整的网络的发起函数参数的定义,与数据解析的函数
    import Foundation
    import Alamofire
    import SwiftyJSON
    
    /// 商品详情请求
    struct goodsParticulars: Request {
    
        var goodsId: String
        
        /// 多个参数继续书写...
        
        var path: String {
            return Api.goodsParticularsURL
        }
        
        var method: HTTPMethod = .post
        
        var parameter: [String : AnyObject] {
            return ["goods_id": goodsId as AnyObject]
        }
        
        typealias Analysis = ParticularsAnalysis
    }
    
    extension ParticularsAnalysis: Decodable {
        static func parse(anyData: Any) -> ParticularsAnalysis? {
            return ParticularsAnalysis(anyData: anyData)
        }
    }
    
    struct ParticularsAnalysis {
        
        var message: Bool
        var tempData: Any
        
        init?(anyData: Any) {
            
            let obj = JSON(anyData)
            
            guard let name = obj["errno"].int else {
                self.message = false
                return nil
            }
            
            if name == 2000 {
                self.message = true
                self.tempData = anyData
            } else {
                self.message = false
                self.tempData = anyData
                
            }
        }
    }
    
    • 一个完整的网络请求的发起
    
           ///  函数的发起处
            SessionRequestSender().send(goodsParticulars(goodsId: "580", method: .post), analysis: { ParticularsAnalysis in
    //            这里对结果的处理
    //            ParticularsAnalysis?.message
    //            ParticularsAnalysis?.tempData
                
            })
    
    整个思想流程图:
    Created with Raphaël 2.1.2网络请求的发起请求发起处请求发起处请求/返回的数据处理中心请求/返回的数据处理中心请求协议、解析协议请求协议、解析协议真正的网络发起中心真正的网络发起中心参数的装载继承请求、解析协议及协议的扩展调用网络发起中心请求得到的数据

    最后附上代码,进入点击POP文件夹即可

    同时希望您能给个小星星啦!

    欢迎关注我的 微博