2025-05-12 14:20:00 +08:00

224 lines
7.5 KiB
Swift

//
// SPNetwork.swift
// MoviaBox
//
// Created by on 2025/4/8.
//
import UIKit
import Moya
import SmartCodable
///
let SPNetworkCodeSucceed = 200
class SPNetwork: NSObject {
///token线
private static let operationQueue = OperationQueue()
private static var tokenOperation: BlockOperation?
static let provider = MoyaProvider<SPApi>(requestClosure: CustomApiTimeoutClosure)
static func request<T>(parameters: SPNetworkParameters, completion: ((_ response: SPNetworkResponse<T>) -> Void)?) {
if SPLoginManager.manager.token == nil {
self.requestToken(completer: nil)
}
if let tokenOperation = self.tokenOperation, parameters.path != "/customer/register" {
let requestOperation = BlockOperation {
let semaphore = DispatchSemaphore(value: 0)
_request(parameters: parameters) { (response: SPNetworkResponse<T>) in
semaphore.signal()
completion?(response)
}
semaphore.wait()
}
///
requestOperation.addDependency(tokenOperation)
operationQueue.addOperation(requestOperation)
} else {
_request(parameters: parameters, completion: completion)
}
}
@discardableResult
static func _request<T>(parameters: SPNetworkParameters, completion: ((_ response: SPNetworkResponse<T>) -> Void)?) -> Cancellable {
if parameters.isLoding {
SPHUD.show()
}
return provider.requestCustomJson(.request(parameters: parameters)) { (result) in
if parameters.isLoding {
SPHUD.dismiss()
}
guard let completion = completion else {return}
_resultDispose(parameters: parameters, result: result, completion: completion)
}
}
private static func _resultDispose<T>(parameters: SPNetworkParameters, result: Result<Moya.Response, MoyaError>, completion: ((_ response: SPNetworkResponse<T>) -> Void)?) {
switch result {
case .success(let response):
let code = response.statusCode
if code == 401 || code == 402 || code == 403 {
if parameters.path == "/customer/register" {
var res = SPNetworkResponse<T>()
res.code = -1
if parameters.isToast {
SPToast.show(text: "movia_error".localized)
}
completion?(res)
} else {
///token
self.requestToken(completer: nil)
///
if let tokenOperation = self.tokenOperation, parameters.path != "/customer/register" {
let requestOperation = BlockOperation {
let semaphore = DispatchSemaphore(value: 0)
_request(parameters: parameters) { (response: SPNetworkResponse<T>) in
semaphore.signal()
completion?(response)
}
semaphore.wait()
}
///
requestOperation.addDependency(tokenOperation)
operationQueue.addOperation(requestOperation)
}
}
return
}
do {
let tempData = try response.mapString()
spLog(message: parameters.parameters)
spLog(message: parameters.path)
DispatchQueue.global().async {
let response: SPNetworkResponse<T> = _deserialize(data: tempData)
DispatchQueue.main.async {
if response.code != SPNetworkCodeSucceed {
if parameters.isToast {
SPToast.show(text: response.msg)
}
}
completion?(response)
}
}
} catch {
var res = SPNetworkResponse<T>()
res.code = -1
if parameters.isToast {
SPToast.show(text: "movia_error".localized)
}
completion?(res)
}
case .failure(let error):
spLog(message: error)
var res = SPNetworkResponse<T>()
res.code = -1
if parameters.isToast {
SPToast.show(text: "movia_network_toast_01".localized)
}
completion?(res)
break
}
}
///
static private func _deserialize<T>(data: String) -> SPNetworkResponse<T> {
var response: SPNetworkResponse<T>?
let time = Date().timeIntervalSince1970
let decrypted = CryptorService.decrypt(data: data)
spLog(message: decrypted)
response = SPNetworkResponse<T>.deserialize(from: decrypted)
response?.rawData = decrypted
spLog(message: Date().timeIntervalSince1970 - time)
if let response = response {
return response
} else {
var response = SPNetworkResponse<T>()
response.code = -1
response.msg = "movia_error".localized
return response
}
}
}
extension SPNetwork {
///token
static func requestToken(completer: ((_ token: SPTokenModel?) -> Void)?) {
guard self.tokenOperation == nil else {
completer?(nil)
return
}
self.tokenOperation = BlockOperation(block: {
let semaphore = DispatchSemaphore(value: 0)
let param = SPNetworkParameters(path: "/customer/register")
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<SPTokenModel>) in
if let token = response.data {
SPLoginManager.manager.setLoginToken(token: token)
}
do { semaphore.signal() }
self.tokenOperation = nil
completer?(response.data)
}
semaphore.wait()
})
operationQueue.addOperation(self.tokenOperation!)
}
}
extension MoyaProvider {
@discardableResult
func requestCustomJson(_ target: Target, callbackQueue: DispatchQueue? = nil, completion: Completion?) -> Cancellable {
return request(target, callbackQueue: callbackQueue) { (result) in
guard let completion = completion else {return}
completion(result)
}
}
}
let CustomApiTimeoutClosure = {(endpoint: Endpoint, closure: MoyaProvider<SPApi>.RequestResultClosure) -> Void in
if var urlRequest = try? endpoint.urlRequest() {
///
urlRequest.cachePolicy = .reloadIgnoringCacheData
urlRequest.timeoutInterval = 30
closure(.success(urlRequest))
} else {
closure(.failure(MoyaError.requestMapping(endpoint.url)))
}
#if DEBUG ///
//print(try? endpoint.urlRequest() )
#endif
}