2.9 面向协议编程_示例: Http请求数据

根据 职责分离 原则: 分为: 1. 数据实体类; 2.网络请求类; 3. 网络连接类;

  • 1.0 数据实体 要遵循 协议:
import Foundation
protocol DecodableEntity
{
    static func parse(data: Data) -> Self? //将Data数据转成数据实体本身;
}
    1. 1 数据实体类
import Foundation

// 用结构体来作为数据实体 (结构体更为轻量)
struct User
{
    //--- 属性 : (对应服务器返回的数据)
    let name: String
    let hobbies: String
    let birthdate: String
    
    //--- 初始化:
    init?(data: Data)
    {
        guard let obj = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else
        {
            return nil
        }
        guard let name = obj["name"] as? String else
        {
            return nil
        }
        guard let hobbies = obj["hobbies"] as? String else
        {
            return nil
        }
        guard let birthdate = obj["birthdate"] as? String else
        {
            return nil
        }
        
        self.name = name
        self.hobbies = hobbies
        self.birthdate = birthdate
    }
}

// 对类扩展协议,使得 类遵循协议:
extension User: DecodableEntity
{
    // 实现协议方法:
    static func parse(data: Data) -> User?
    {
        return User(data: data)
    }
}

  • 2.0 网络请求 协议:
import Foundation

// 网络请求方式:
enum HttpRequestMethod: String
{ 
    case GET
    case POST
    case PUT
    case DELETE
}

// 协议:
protocol HttpRequest
{
    var path: String { get }
    var method: HttpRequestMethod { get }
    var parameter: [String: Any] { get }
    
    associatedtype Response: DecodableEntity  //泛型; (因为请求到的具体数据不确定)
}

// 对协议进行扩展, 以默认实现方法:
extension HttpRequest
{  
    var host : String { return "http://hdjc8.com" }
}
  • 2.1 网络请求类: (发起请求者)
import Foundation

struct UserHttpRequest: HttpRequest  // 遵循协议;
{    
    //  请求参数:
    var path = "/json/jsonUser.json"
    let method: HttpRequestMethod = .GET
    let parameter: [String: Any] = [:]
        
    // 实现协议: 确定请求到的数据类型:
    typealias Response = User 
}
    1. 网络连接类
import Foundation

// 协议: 用泛型(遵循 HttpRequest 的类型)
protocol Client
{
    func send<T: HttpRequest>(_ request: T, handler: @escaping (T.Response?) -> Void)
}

// 遵循协议:
struct HttpClient: Client
{
    // 实现 协议方法:  发起网络请求
    func send<T: HttpRequest>(_ request: T, handler: @escaping (T.Response?) -> Void)
    {
        let hostAndPath = request.host.appending(request.path)
        var urlRequest = URLRequest(url: URL(string: hostAndPath)!)
        urlRequest.httpMethod = request.method.rawValue
        
        let dataTask = URLSession.shared.dataTask(with: urlRequest)
        {
            data, _, error in
            
            /// 解析成数据实体:  ( data为服务器返回的数据)
            guard let data = data, let entity = T.Response.parse(data: data)else {
                return
            }

            /// 返回主线程:
            DispatchQueue.main.async { handler(entity) }
        }
        dataTask.resume()
    }
}
  • 使用 测试:
import UIKit
class ViewController: UIViewController
{
    override func viewDidLoad(){
        super.viewDidLoad()
        yeTest()
    }
    
    func yeTest(){
        HttpClient().send(UserHttpRequest())
        { user in
            if let user = user
            {
                print("user.name: \(user.name)")
                print("user.birthdate: \(user.birthdate)")
                print("user.hobbies: \(user.hobbies)")
            }
        }
    }
}
截屏2023-01-24 22.44.01.png
截屏2023-01-24 22.44.36.png
截屏2023-01-24 22.45.14.png
截屏2023-01-24 22.45.20.png
截屏2023-01-24 22.45.35.png
截屏2023-01-24 22.46.05.png
截屏2023-01-24 22.46.10.png
截屏2023-01-24 22.46.14.png
截屏2023-01-24 22.46.16.png
截屏2023-01-24 22.46.19.png
截屏2023-01-24 22.46.22.png
截屏2023-01-24 22.46.30.png
截屏2023-01-24 22.47.06.png
截屏2023-01-24 22.47.10.png
截屏2023-01-24 22.47.18.png
截屏2023-01-24 22.47.45.png
截屏2023-01-24 22.47.56.png
截屏2023-01-24 22.48.13.png
截屏2023-01-24 22.49.17.png
截屏2023-01-24 22.49.27.png
截屏2023-01-24 22.49.30.png
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容