229 lines
6.8 KiB
Swift
229 lines
6.8 KiB
Swift
//
|
|
// YMRequestX.swift
|
|
// yinmeng-ios
|
|
//
|
|
// Created by MaiMang on 2024/2/2.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
public struct YMRequestX {
|
|
/// Maps data received from the signal into a JSON object.
|
|
public static func mapJSON<T>(_ type: T.Type, named: String, forResource: String = "RxNetworks") -> T? {
|
|
guard let data = jsonData(named, forResource: forResource) else {
|
|
return nil
|
|
}
|
|
let json = try? JSONSerialization.jsonObject(with: data, options: .allowFragments)
|
|
return json as? T
|
|
}
|
|
|
|
/// Read json data
|
|
public static func jsonData(_ named: String, forResource: String = "RxNetworks") -> Data? {
|
|
let bundle: Bundle?
|
|
if let bundlePath = Bundle.main.path(forResource: forResource, ofType: "bundle") {
|
|
bundle = Bundle.init(path: bundlePath)
|
|
} else {
|
|
bundle = Bundle.main
|
|
}
|
|
guard let path = ["json", "JSON", "Json"].compactMap({
|
|
bundle?.path(forResource: named, ofType: $0)
|
|
}).first else {
|
|
return nil
|
|
}
|
|
let contentURL = URL(fileURLWithPath: path)
|
|
return try? Data(contentsOf: contentURL)
|
|
}
|
|
|
|
public static func toJSON(form value: Any, prettyPrint: Bool = false) -> String? {
|
|
guard JSONSerialization.isValidJSONObject(value) else {
|
|
return nil
|
|
}
|
|
var jsonData: Data? = nil
|
|
if prettyPrint {
|
|
jsonData = try? JSONSerialization.data(withJSONObject: value, options: [.prettyPrinted])
|
|
} else {
|
|
jsonData = try? JSONSerialization.data(withJSONObject: value, options: [])
|
|
}
|
|
guard let data = jsonData else { return nil }
|
|
return String(data: data ,encoding: .utf8)
|
|
}
|
|
|
|
public static func toDictionary(form json: String) -> [String : Any]? {
|
|
guard let jsonData = json.data(using: .utf8),
|
|
let object = try? JSONSerialization.jsonObject(with: jsonData, options: []),
|
|
let result = object as? [String : Any] else {
|
|
return nil
|
|
}
|
|
return result
|
|
}
|
|
|
|
public static func keyWindow() -> UIWindow? {
|
|
if #available(iOS 13.0, *) {
|
|
return UIApplication.shared.connectedScenes
|
|
.filter { $0.activationState == .foregroundActive }
|
|
.first(where: { $0 is UIWindowScene })
|
|
.flatMap({ $0 as? UIWindowScene })?.windows
|
|
.first(where: \.isKeyWindow)
|
|
} else {
|
|
return UIApplication.shared.keyWindow
|
|
}
|
|
}
|
|
|
|
public static func topViewController() -> UIViewController? {
|
|
let window = UIApplication.shared.delegate?.window
|
|
guard window != nil, let rootViewController = window?!.rootViewController else {
|
|
return nil
|
|
}
|
|
return self.getTopViewController(controller: rootViewController)
|
|
}
|
|
|
|
public static func getTopViewController(controller: UIViewController) -> UIViewController {
|
|
if let presentedViewController = controller.presentedViewController {
|
|
return self.getTopViewController(controller: presentedViewController)
|
|
} else if let navigationController = controller as? UINavigationController {
|
|
if let topViewController = navigationController.topViewController {
|
|
return self.getTopViewController(controller: topViewController)
|
|
}
|
|
return navigationController
|
|
} else if let tabbarController = controller as? UITabBarController {
|
|
if let selectedViewController = tabbarController.selectedViewController {
|
|
return self.getTopViewController(controller: selectedViewController)
|
|
}
|
|
return tabbarController
|
|
} else {
|
|
return controller
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// MARK: - HUD
|
|
extension YMRequestX {
|
|
/// 移除窗口所有HUD
|
|
public static func removeAllAtLevelStatusBarWindow() {
|
|
SharedDriver.shared.removeAllAtLevelStatusBarWindow()
|
|
}
|
|
|
|
/// 移除所有加载HUD
|
|
public static func removeLoadingHUDs() {
|
|
SharedDriver.shared.removeLoadingHUDs()
|
|
}
|
|
|
|
public static func readHUD(key: String) -> LevelStatusBarWindowController? {
|
|
SharedDriver.shared.readHUD(key: key)
|
|
}
|
|
|
|
public static func saveHUD(key: String, window vc: LevelStatusBarWindowController) {
|
|
SharedDriver.shared.saveHUD(key: key, window: vc)
|
|
}
|
|
|
|
@discardableResult
|
|
public static func removeHUD(key: String?) -> LevelStatusBarWindowController? {
|
|
SharedDriver.shared.removeHUD(key: key)
|
|
}
|
|
}
|
|
|
|
|
|
// MARK: - 网络相关
|
|
extension YMRequestX {
|
|
|
|
static func maxDelayTime(with plugins: APIPlugins) -> Double {
|
|
let times: [Double] = plugins.compactMap {
|
|
if let p = $0 as? PluginPropertiesable {
|
|
return p.delay
|
|
}
|
|
return 0.0
|
|
}
|
|
let maxTime = times.max() ?? 0.0
|
|
return maxTime
|
|
}
|
|
|
|
static func sortParametersToString(_ parameters: APIParameters?) -> String {
|
|
guard let params = parameters, !params.isEmpty else {
|
|
return ""
|
|
}
|
|
var paramString = "?"
|
|
let sorteds = params.sorted(by: { $0.key > $1.key })
|
|
for index in sorteds.indices {
|
|
paramString.append("\(sorteds[index].key)=\(sorteds[index].value)")
|
|
if index != sorteds.count - 1 { paramString.append("&") }
|
|
}
|
|
return paramString
|
|
}
|
|
|
|
static func requestLink(with target: TargetType, parameters: APIParameters? = nil) -> String {
|
|
let parameters: APIParameters? = parameters ?? {
|
|
if case .requestParameters(let parame, _) = target.task {
|
|
return parame
|
|
}
|
|
return nil
|
|
}()
|
|
let paramString = sortParametersToString(parameters)
|
|
return target.baseURL.absoluteString + target.path + paramString
|
|
}
|
|
|
|
static func toJSON(with response: Moya.Response) throws -> APISuccessJSON {
|
|
let response = try response.filterSuccessfulStatusCodes()
|
|
return try response.mapJSON()
|
|
}
|
|
|
|
static func loadingSuffix(key: SharedDriver.Key?) -> Bool {
|
|
guard let key = key else { return false }
|
|
if let suffix = key.components(separatedBy: "_").last, YMRequestConfig.loadingPluginNames.contains(suffix) {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
static func setupPluginsAndKey(_ key: String, plugins: APIPlugins) -> APIPlugins {
|
|
var plugins = plugins
|
|
YMRequestX.setupBasePlugins(&plugins)
|
|
return plugins.map({
|
|
if var plugin = $0 as? PluginPropertiesable {
|
|
plugin.plugins = plugins
|
|
plugin.key = key + "_" + plugin.pluginName
|
|
return plugin
|
|
}
|
|
return $0
|
|
})
|
|
}
|
|
}
|
|
|
|
// MARK: - 模块宏定义
|
|
extension YMRequestX {
|
|
|
|
/// 注入默认插件
|
|
static func setupBasePlugins(_ plugins: inout APIPlugins) {
|
|
var plugins_ = plugins
|
|
if let others = YMRequestConfig.basePlugins {
|
|
plugins_ += others
|
|
}
|
|
#if RXNETWORKS_PLUGINGS_INDICATOR
|
|
if NetworkConfig.addIndicator, !plugins_.contains(where: { $0 is NetworkIndicatorPlugin}) {
|
|
let Indicator = NetworkIndicatorPlugin.shared
|
|
plugins_.insert(Indicator, at: 0)
|
|
}
|
|
#endif
|
|
#if DEBUG && RXNETWORKS_PLUGINGS_DEBUGGING
|
|
if NetworkConfig.addDebugging, !plugins_.contains(where: { $0 is NetworkDebuggingPlugin}) {
|
|
let Debugging = NetworkDebuggingPlugin.init()
|
|
plugins_.append(Debugging)
|
|
}
|
|
#endif
|
|
plugins = plugins_
|
|
}
|
|
|
|
/// 是否存在请求头插件
|
|
static func hasNetworkHttpHeaderPlugin(_ key: String) -> [String: String]? {
|
|
#if RXNETWORKS_PLUGINGS_HTTPHEADER
|
|
let plugins = SharedDriver.shared.readRequestPlugins(key)
|
|
if let p = plugins.first(where: { $0 is NetworkHttpHeaderPlugin }) {
|
|
return (p as? NetworkHttpHeaderPlugin)?.dictionary
|
|
}
|
|
#endif
|
|
return nil
|
|
}
|
|
|
|
}
|
|
|