ESNetworkManager 是一个依赖 Alamofire 的库,使得创建新的工作请求变得容易,并支持响应映射。
版本兼容性
以下是当前 Swift 兼容性分解
Swift 版本 | 网络版本 |
---|---|
5.X | master |
安装
CocoaPods
将以下内容添加到您的 Podfile
pod 'ESNetworkManager'
pod 'ESNetworkManager/Core'
pod 'ESNetworkManager/Promise'
pod 'ESNetworkManager/Rx'
pod 'ESNetworkManager/ObjectMapper'
您还需要确保您已经选择了使用框架
use_frameworks!
然后使用 CocoaPods 0.36 或更高版本运行 pod install
。
使用说明
初始化 ESNetworkRequest
let request = ESNetworkRequest(base: "https://sample.com", path: "api/path")
request.parameters = [:]
request.headers = [:]
request.encoding = JSONEncoding.default
request.method = .post
request.selections = []
print(request)
ESNetworkManager 执行 ESNetworkRequest 并完成
func login(email: String, password: String) {
let request = ESNetworkRequest(base: "https://sample.com", path: "api/login")
request.parameters = ["email": email, "password": password]
request.encoding = JSONEncoding.default
request.method = .post
ESNetworkManager.execute(request: request) { (response: ESNetworkResponse<User>) in
guard case .success(let user) = response else {
return
}
print(user.name)
}
}
上传多部分文件
func upload(avatar: UIImage) {
let data = avatar.jpegData(compressionQuality: 0.5)!
let file = MPFile(data: data, key: "file", name: "image.jpeg", memType: "image/jpeg")
let request = ESNetworkRequest(base: "https://sample.com", path: "api/upload")
request.parameters = [:]
request.encoding = JSONEncoding.default
request.method = .post
ESNetworkManager.upload(data: .multipart([file]), request: request, progress: { progress in
print(progress.frationCompleted)
}) { (response: ESNetworkResponse<String>) in
guard case .success(let imageUrlString) = response else {
return
}
print(imageUrlString)
}
}
下载文件
func downloadFile() {
let request = ESNetworkRequest(base: "https://sample.com", path: "api/file.mp4")
ESNetworkManager.download(request: request, progress: { (progress) in
print(progress.fractionCompleted)
}) { (response) in
guard case .success(let url) = response else {
return
}
print(url.absoluteString)
}
}
会话管理器
覆盖会话管理器
class NetworkManager: ESNetworkManager {
static let session: Session = {
let manager = ServerTrustManager(evaluators: ["serverurl.com": DisabledEvaluator()])
let configuration = URLSessionConfiguration.af.default
return Session(configuration: configuration, serverTrustManager: manager)
}()
override class var Manager: Session {
return session
}
}
数据响应映射
如果你有一个带有预定义错误或错误服务器消息的基本响应,如以下登录响应情况,则使用高级数据响应映射
let json_success = """
{
"status": 200,
"message": "Welcom",
"content": {"token": "2e13eer1rt13tvxcvz"}
}
"""
let json_fail = """
{
"status": 1002,
"message": "Wrong Email or password"
}
"""
简单覆盖数据响应映射
class NetworkManager: ESNetworkManager {
override class func map(_ response: AFDataResponse<Any>) -> ESNetworkResponse<JSON> {
if let error = response.error {
return .failure(error)
}
let json = JSON(response.value)
let status: Int = json.status.value() ?? 0
switch status {
case 200:
return .success(json.content)
case let code:
return .failure(NSError.init(error: json.message.value() ?? "", code: code))
}
}
}
// Example For Wrong Email or password
login(email: "email", password: "password") { (response) in
guard case .error(let error) = response else {
return
}
print(error.localizedDescription) // --> Wrong Email or password
print(error.statusCode) // --> 1002
}
JSON
JSON是一个枚举,其用法类似于JavaScript对象而不是字典,例如
let dictionary: [String: Any] = ["name": "Demo User",
"age": 41,
"type": 1,
"verified": 0,
"activated": true,
"phones": ["134234", "532412"],
"adddress": ["title": "Cairo", "latitude": "12.23123", "logintude": "41.12323"],
"family": [["name": "Demo Son", "age": 19, "activated": false]]]
let json = JSON(dictionary)
json.name.value() // --> Demo User
json.phones.0.value() // --> 134234
json.adddress.title.value() // --> Cairo
json.family.0.name.value() // --> Demo Son
PromiseKit 扩展
import PromiseKit
func login(email: String, password: String) -> Promise<String>{
return ESNetworkManager.execute(request: request)
}
func getProfile(token: String) -> Promise<User>{
return ESNetworkManager.execute(request: request)
}
// Example
func login() {
firstly {
login(email: "[email protected]", password: "password")
}.then {
getProfile(token: $0)
}.done { (user) in
print(user.name)
}.catch { (error) in
print(error.localizedDescription)
}
}
RxSwift 扩展
import RxSwift
func login(email: String, password: String) -> Single<String>{
return ESNetworkManager.execute(request: request)
}
func getProfile(token: String) -> Single<User>{
return ESNetworkManager.execute(request: request)
}
// Example
func login() {
login(email: "[email protected]", password: "password")
.flatMap({getProfile(token: $0)})
.subscribe(onSuccess: { (user) in
print(user.name)
}) { (error) in
print(error.localizedDescription)
}.disposed(by: disposeBag)
}
请求选择
用于选择特定响应的情况,例如,用户成功登录后返回的 JSON 响应
let response = """
{
"staus": 200
"messase" : "Success"
"content": {
"id": 12,
"name": "Demo User",
"email": "[email protected]",
"token": "Token"
"phones": ["01000000000", "02000000000"]
}
}
"""
不需要创建类似这样的模型
class Model {
var status: Int?
var messase: Int?
var content: User?
}
只需设置请求选择(键或索引),例如
func login(email: String, password: String) {
request.selection = [.key("content")]
ESNetworkManager.execute(request: request) { (response: ESNetworkResponse<User>) in
guard case .success(let user) = response else {
return
}
print(user.name)
}
}
或者
func login(email: String, password: String) {
request.selection = [.key("content"), .key("token")]
ESNetworkManager.execute(request: request) { (response: ESNetworkResponse<String>) in
guard case .success(let token) = response else {
return
}
print(token) // --> Token
}
}
或者
func login(email: String, password: String) {
request.selection = [.key("content"), .key("phones"), .index(0)]
ESNetworkManager.execute(request: request) { (response: ESNetworkResponse<String>) in
guard case .success(let phone) = response else {
return
}
print(phone) // --> 01000000000
}
}
响应映射
-
为 Codable、ObjectMapper 和 RawRepresentable 实现了默认映射
-
在这种情况下,API 响应
let dictionary: [String: Any] = ["name": "Demo User",
"age": 41,
"type": 1,
"verified": 0,
"activated": true,
"phones": ["134234", "532412"],
"adddress": ["title": "Cairo", "latitude": "12.23123", "logintude": "41.12323"],
"family": [["name": "Demo Son", "age": 19, "activated": false]]]
Codable
Codable
func login(email: String, password: String) {
ESNetworkManager.execute(request: request) { (response: ESNetworkResponse<User>) in
guard case .success(let user) = response else {
return
}
print(user.name) // --> Demo User
}
}
class User: Codable {
var name = ""
var age = ""
var activated = false
private enum CodingKeys: String, CodingKey {
case name, age, activated
}
}
字符串
func login(email: String, password: String) {
request.selection = [.key("name")]
ESNetworkManager.execute(request: request) { (response: ESNetworkResponse<String>) in
guard case .success(let name) = response else {
return
}
print(name) // --> Demo User
}
}
数组
func login(email: String, password: String) {
request.selection = [.key("phones")]
ESNetworkManager.execute(request: request) { (response: ESNetworkResponse<[String]>) in
guard case .success(let phones) = response else {
return
}
print(phones) // --> ["134234", "532412"]
}
}
ObjectMapper
func login(email: String, password: String) {
ESNetworkManager.execute(request: request) { (response: ESNetworkResponse<User>) in
guard case .success(let user) = response else {
return
}
print(user.name) // --> Demo User
}
}
class User: Mappable {
var name = ""
var age = ""
var activated = false
required init?(map: Map) {}
func mapping(map: Map) {
name <- "name"
age <- "age"
activated <- "activated"
}
}
RawRepresentable
func login(email: String, password: String) {
request.selection = [.key("type")]
ESNetworkManager.execute(request: request) { (response: ESNetworkResponse<UserType>) in
guard case .success(let type) = response else {
return
}
print(type) // --> UserType.admin
}
}
enum UserType: Int {
case admin = 1
}
其他映射
// Mapping Protocol
protocol MappingTool {
init(json: [String: Any])
}
// SubClassing from ESNetworkResponseMapper<T>
class MappingToolNetworkResponseMapper<T>: ESNetworkResponseMapper<T> where T: MappingTool {
override func map(_ response: ESNetworkResponse<JSON>, selections: [Selection]) -> ESNetworkResponse<T> {
guard case .success(var value) = response else {
return .failure(response.error!)
}
value = value[selections]
guard let json = value.object as? [String: Any] else {
return .failure(NSError.init(error: "Unable to get json from \(value)", code: -1))
}
return .success(T.init(json: json))
}
}
func login(email: String, password: String) {
ESNetworkManager.execute(request: request,
mapper: MappingToolNetworkResponseMapper()) { (response: ESNetworkResponse<MUser>) in
guard case .success(let user) = response else {
return
}
print(user.name!) // --> Demo User
}
}
// Declare a class
class MUser: MappingTool {
var name: String?
var age: Int?
required init(json: [String : Any]) {
name = json["name"] as? String
age = json["age"] as? Int
}
}
许可证
ESNetworkManager遵循MIT许可证发布。 查看LICENSE获取详细信息。