|
//
// NetworkApi.swift
// PaiAi
//
// Created by FFIB on 2017/9/29.
// Copyright © 2017年 yb. All rights reserved.
//
import Foundation
import Alamofire
class NetworkApi {
open static let share = NetworkApi()
typealias FailureHandler = ((HTTPURLResponse?) -> Void)
typealias ProgressHandler = (() -> Void)
typealias FinishHandler = (() -> Void)
private let sessionManager: SessionManager
private var httpRequests = [Request]()
private var currentRequests: Request? = nil
var finishHander: FinishHandler = {}
var failureHandler: FailureHandler = { response in
guard let status = response?.statusCode else {
return
}
let manager = NetworkReachabilityManager()
manager?.listener = { networkStatus in
guard let visibleView = UIApplication.shared.keyWindow else{
return
}
if networkStatus == .notReachable || networkStatus == .unknown {
FFToastView.showToast(inView: visibleView, withText: "当前网络状态不好")
return
}
if status >= 500 {
FFToastView.showToast(inView: visibleView, withText: "服务器出现异常")
}else if status >= 400 {
assert(true, "client error")
}else if status >= 300 {
assert(true, "重定向问题")
}
}
}
init() {
let configuration = URLSessionConfiguration.default
configuration.httpAdditionalHeaders = SessionManager.defaultHTTPHeaders
sessionManager = Alamofire.SessionManager(configuration: configuration)
sessionManager.retrier = OAuthHandler()
}
@discardableResult
public func failure(handler: @escaping FailureHandler) -> NetworkApi {
failureHandler = handler
return self
}
@discardableResult
public func finish(handler: @escaping FinishHandler) -> NetworkApi {
finishHander = handler
return self
}
@discardableResult
public func post<T: NetworkRequest>(request: T,
handler: @escaping ([T.NetworkResponse]) -> Void)
-> NetworkApi
where T.NetworkResponse: GroupParsable {
let request = sessionManager.request(request.host + request.path.rawValue,
method: .post,
parameters: request.parameter)
.responseJSON {[weak self] (res) in
guard let weakself = self else {
return
}
weakself.finishHander()
if let index = weakself.httpRequests.index(where: { $0.request == res.request }) {
weakself.httpRequests.remove(at: index)
}
switch res.result {
case .success(let value):
guard let data = value as? [String: AnyObject] else {
return
}
handler(T.NetworkResponse.parse(datas: data))
case .failure(_):
weakself.failureHandler(res.response)
}
}
httpRequests.append(request)
return self
}
@discardableResult
public func post<T: NetworkRequest>(request: T,
handler: @escaping (T.NetworkResponse) -> Void)
-> NetworkApi
where T.NetworkResponse: SingleParsable{
let request = sessionManager.request(request.host + request.path.rawValue,
method: .post,
parameters: request.parameter)
.responseJSON {[weak self] (res) in
guard let weakself = self else {
return
}
weakself.finishHander()
if let index = weakself.httpRequests.index(where: { $0.request == res.request }) {
weakself.httpRequests.remove(at: index)
}
switch res.result {
case .success(let value):
guard let data = value as? [String: AnyObject] else {
return
}
handler(T.NetworkResponse.parse(data: data))
case .failure(_):
weakself.failureHandler(res.response)
}
}
httpRequests.append(request)
return self
}
@discardableResult
public func post(param: [String: AnyObject],
url: Interfaces,
handler: @escaping ([String: AnyObject]) -> Void)
-> NetworkApi {
let request = sessionManager.request(Interfaces.baseUrl.rawValue + url.rawValue,
method: .post,
parameters: param)
.responseJSON {[weak self] (res) in
guard let weakself = self else {
return
}
weakself.finishHander()
switch res.result {
case .success(let value):
guard let data = value as? [String: AnyObject] else {
return
}
handler(data)
case .failure(_):
weakself.failureHandler(res.response)
}
if let index = weakself.httpRequests.index(where: { $0.request == res.request }) {
weakself.httpRequests.remove(at: index)
}
}
httpRequests.append(request)
return self
}
@discardableResult
public func get(param: [String: AnyObject]?, url: String,
handler: @escaping ([String: AnyObject]) -> Void) -> NetworkApi {
let final = url.hasPrefix("http") ? url : Interfaces.baseUrl.rawValue + url
let request = sessionManager.request(final,
method: .get,
parameters: param)
.responseJSON {[weak self] (res) in
guard let weakself = self else {
return
}
weakself.finishHander()
if let index = weakself.httpRequests.index(where: { $0.request == res.request }) {
weakself.httpRequests.remove(at: index)
}
switch res.result {
case .success(let value):
guard let data = value as? [String: AnyObject] else {
return
}
handler(data)
case .failure(_):
weakself.failureHandler(res.response)
}
}
httpRequests.append(request)
return self
}
@discardableResult
public func get<T: NetworkRequest>(request: T,
handler: @escaping ([T.NetworkResponse]) -> Void)
-> NetworkApi
where T.NetworkResponse: GroupParsable {
let request = sessionManager.request(request.host + request.path.rawValue,
method: .get,
parameters: request.parameter)
.responseJSON {[weak self] (res) in
guard let weakself = self else {
return
}
weakself.finishHander()
if let index = weakself.httpRequests.index(where: { $0.request == res.request }) {
weakself.httpRequests.remove(at: index)
}
switch res.result {
case .success(let value):
guard let data = value as? [String: AnyObject] else {
return
}
handler(T.NetworkResponse.parse(datas: data))
case .failure(_):
weakself.failureHandler(res.response)
}
}
httpRequests.append(request)
return self
}
@discardableResult
public func download<T: NetworkRequest>(request: T) -> NetworkApi {
sessionManager.download(request.host + request.path.rawValue,
method: .get,
parameters: request.parameter,
to: nil)
return self
}
@discardableResult
public func upload(param: [String: AnyObject], url: String,
handler: @escaping ([String: AnyObject]) -> Void) -> NetworkApi {
sessionManager.upload(multipartFormData: { (multiPartData) in
for (key, value) in param {
if let v = value as? FileModel {
multiPartData.append(v.fileData, withName: v.name, fileName: v.fileName, mimeType: v.mimeType)
}else {
var res: Data
if let v = value as? String, let data = v.data(using: String.Encoding.utf8) {
res = data
}else if let v = value as? NSNumber, let data = "\(v)".data(using: String.Encoding.utf8){
res = data
}else {
continue
}
multiPartData.append(res, withName: key)
}
}
}, to: Interfaces.baseUrl.rawValue + url) {[weak self] (res) in
guard let weakself = self else {
return
}
weakself.finishHander()
switch res {
case .failure( _):
break
case .success(let request,_,_):
request.responseJSON(completionHandler: { (response) in
guard let value = response.value as? [String: AnyObject] else {
return
}
handler(value)
})
}
}
return self
}
deinit {
httpRequests.forEach { (request) in
request.cancel()
}
}
}
//extension request retrier
extension NetworkApi {
public struct OAuthHandler: RequestRetrier {
init() {}
public func should(_ manager: SessionManager, retry request: Request, with error: Error, completion: @escaping RequestRetryCompletion) {
if let response = request.response, response.statusCode == 401 {
completion(true, 1.0) // 1秒后重试
} else {
completion(false, 0.0) // 不重连
}
}
}
}
|