- 协议类: YeProtocolForHttpData.swift
//
// YeProtocolForHttpData.swift
// TyeProject
//
// Created by Tye on 20../../..
//
import Foundation
///== 1. 数据实体的基础协议: 所有数据实体都须遵循它;
protocol YeProtocolForDataEntity
{
//【静态方法】将二进制Data数据 (编码)转换为 本身实例对象 的方法:
static func yeDataToSelf(eData:Data) -> Self?
}
///== 2. 网络请求的基础协议: 所有的网络请求都须遵循它;
protocol YeProtocolForHttp {
var eStrUrl: String {get} // 请求地址;
var eEnumType: YeHttpRequestTypeEnum { get } //请求方式;
var eDicParameter: [String: Any] { get } // 请求传递的参数;
// 泛型: 服务器返回的数据实体,(遵循数据实体协议的泛型,因为不同的Url返回不同的实体)
associatedtype eDataEntity: YeProtocolForDataEntity
}
///-- 扩展一个属性: ( 默认实现: )
extension YeProtocolForHttp{
var eHost : String {return "https://www.baidu.com/"} // TODO: Url主地址;
}
// 请求方式: 共有9种, 常见的4种:
enum YeHttpRequestTypeEnum:String{
case GET
case POST
case PUT
case DELETE
}
- 网络请求类: YeHttpRequest.swift
//
// YeHttpRequest.swift
// TyeProject
//
// Created by Tye on 20../../..
//
import Foundation
protocol YeProtocoToHttpRequest{
// 定义为泛型,这样可以接收所有的网络请求:
func yeSend<T:YeProtocolForHttp>(_ eRequest: T, eHandler: @escaping (T.eDataEntity?) -> Void)
}
// 执行网络请求:
struct YeHttpRequest: YeProtocoToHttpRequest{
func yeSend<T>(_ eRequest: T, eHandler: @escaping (T.eDataEntity?) -> Void) where T : YeProtocolForHttp {
let eStrUrl = eRequest.eHost.appending(eRequest.eStrUrl) //拼接处出完整的请求地址;
var eURLRequest = URLRequest(url: URL(string: eStrUrl)!)
eURLRequest.httpMethod = eRequest.eEnumType.rawValue
let eDataTask = URLSession.shared.dataTask(with: eURLRequest) { eData, eURLResponse, eError in
// eData: 从服务器获得的数据 二进制Data类型; 将其解析为数据实体(协议的方法):
guard let eD = eData, let eEntity = T.eDataEntity.yeDataToSelf(eData: eD) else { return }
DispatchQueue.main.async { // 回到主线程;
eHandler(eEntity)
}
}
eDataTask.resume() //开始任务;
}
//--- or 静态方法:
static func yeSendStatic<T>(_ eRequest: T, eHandler: @escaping (T.eDataEntity?) -> Void) where T : YeProtocolForHttp {
let eStrUrl = eRequest.eHost.appending(eRequest.eStrUrl) //拼接处出完整的请求地址;
var eURLRequest = URLRequest(url: URL(string: eStrUrl)!)
eURLRequest.httpMethod = eRequest.eEnumType.rawValue
let eDataTask = URLSession.shared.dataTask(with: eURLRequest) { eData, eURLResponse, eError in
// eData: 从服务器获得的数据 二进制Data类型; 将其解析为数据实体(协议的方法):
guard let eD = eData, let eEntity = T.eDataEntity.yeDataToSelf(eData: eD) else { return }
DispatchQueue.main.async { // 回到主线程;
eHandler(eEntity)
}
}
eDataTask.resume() //开始任务;
}
}
///== 使用示例: eg
- 数据实体类: YeDataEntityToEg.swift
//
// YeDataEntityToEg.swift
// TyeProject
//
// Created by Tye on 20../../..
//
import Foundation
//--- 为数据实体类扩展协议, 以使其遵循此协议:
extension YeDataEntityToEg: YeProtocolForDataEntity{
// 实现协议方法:(初始化)
static func yeDataToSelf(eData: Data) -> Self? {
return YeDataEntityToEg(eData: eData) as? Self
}
}
//--- 数据实体 必须遵循: NSCopying, NSSecureCoding协议:以支持编解码功能,以持久化保存到磁盘中;
class YeDataEntityToEg: NSObject, NSCoding, NSSecureCoding {
// 协议属性:
static var supportsSecureCoding: Bool = true
// 自定义的 属性字段:
var eID : Int = 0
var eName : String = "Name"
var eAge : String = "15"
var eTye : String = "Tye"
//var eImage : UIImage = UIImage()
// 1. 解析 Json:
init?(eData:Data) {
// 解析 Json 转换成字典:
guard let eObj = try? JSONSerialization.jsonObject(with: eData, options: []) as? [String:Any] else { return nil }
//--- 字段解析:
guard let eIDLS = eObj["id"] as? Int else { return nil }
self.eID = eIDLS
// 二级 字典:
guard let eDic = eObj["dic"] as? [String: Any] else { return nil }
if let eNameLS = eDic["name"] as? String{
self.eName = eNameLS
}
if let eAgeLS = eDic["age"] as? String{
self.eAge = eAgeLS
}
// 三级 字典:
if let eDicT = eDic["dicT"] as? [String: Any] {
if let eTyeLS = eDicT["tye"] as? String {
self.eTye = eTyeLS
}
}
}
//--- 协议方法:
// 2. 解码:
required init?(coder: NSCoder) {
super.init()
self.eID = coder.decodeInteger(forKey: "id")
self.eName = coder.decodeObject(forKey: "name") as! String
self.eAge = coder.decodeObject(forKey: "age") as! String
self.eTye = coder.decodeObject(forKey: "tye") as? String ?? "Tye"
}
// 3. 编码:
func encode(with coder: NSCoder) {
coder.encode(self.eID, forKey: "id")
coder.encode(self.eName, forKey: "name")
coder.encode(self.eAge, forKey: "age")
coder.encode(self.eTye, forKey: "tye")
}
}
- 网络接口类: (接口与数据实体类对应配套) YeHttpToEg.swift
//
// YeHttpRequestToEg.swift
// TyeProject
//
// Created by Tye on 20../../..
//
import Foundation
// 请求: (用结构体更为轻量) , 遵循协议:
struct YeHttpToEg: YeProtocolForHttp{
typealias eDataEntity = YeDataEntityToEg // 确定返回的数据实体类;
var eStrUrl: String = "json/josnUser.json" // 接口: 具体的请求地址;
var eEnumType: YeHttpRequestTypeEnum = .GET
var eDicParameter: [String : Any] = [:]
}
- ViewCtrl 中 调用:
//
// YeUserToEgVC.swift
// TyeProject
//
// Created by Tye on 20../../..
//
import UIKit
import PKHUD
import Toaster
class YeUserToEgVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
yeHttpSendToEg()
}
// 发送Http请求 示例:
func yeHttpSendToEg(){
HUD.show(.progress)
YeHttpRequest().yeSend(YeHttpToEg()) { eDataEntity in
HUD.hide(animated: true)
if let eEntity = eDataEntity{
print("---\(eEntity.eID)--")
print("---\(eEntity.eName)--")
// Save To Loc:
let eBl = TyeTool.yeSaveObjectToUserDefaults(eObject: eEntity, eStrKey: "TyeKeyEntityEg")
}
else
{
Toast(text: "网络错误").show()
}
}
}
}