201 lines
6.2 KiB
Swift
201 lines
6.2 KiB
Swift
|
|
//
|
|||
|
|
// Tools.swift
|
|||
|
|
// Crush
|
|||
|
|
//
|
|||
|
|
// Created by Leon on 2025/7/12.
|
|||
|
|
//
|
|||
|
|
|
|||
|
|
import Foundation
|
|||
|
|
import AdSupport
|
|||
|
|
import AppTrackingTransparency
|
|||
|
|
|
|||
|
|
/// 常用工具和常用字典。
|
|||
|
|
class CLTool {
|
|||
|
|
static let shared = CLTool()
|
|||
|
|
|
|||
|
|
var appVersion: AppVersion?
|
|||
|
|
|
|||
|
|
static func clearTempFolder() {
|
|||
|
|
let fileManager = FileManager.default
|
|||
|
|
let tempFolderPath = NSTemporaryDirectory()
|
|||
|
|
|
|||
|
|
do {
|
|||
|
|
let filePaths = try fileManager.contentsOfDirectory(atPath: tempFolderPath)
|
|||
|
|
for filePath in filePaths {
|
|||
|
|
// dlog("filaPath: \(filePath)")
|
|||
|
|
try fileManager.removeItem(atPath: NSTemporaryDirectory() + filePath)
|
|||
|
|
}
|
|||
|
|
} catch let error as NSError {
|
|||
|
|
print("Could not clear temp folder: \(error.debugDescription)")
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static func feedbackGenerator() {
|
|||
|
|
if #available(iOS 13.0, *) {
|
|||
|
|
let gen = UIImpactFeedbackGenerator(style: .medium) // light震动效果的强弱
|
|||
|
|
gen.prepare() // 反馈延迟最小化
|
|||
|
|
gen.impactOccurred() // 触发效果
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static func syncInputTintColor() {
|
|||
|
|
UITextField.appearance().tintColor = .blue
|
|||
|
|
UITextView.appearance().tintColor = .blue
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// MARK: - public
|
|||
|
|
|
|||
|
|
public func requestAppVersion(block: ((_ appVer: AppVersion?) -> Void)?) {
|
|||
|
|
if let appVer = appVersion {
|
|||
|
|
block?(appVer)
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// CommonProvider.request(.appVersionGet, modelType: AppVersion.self, autoShowErrMsg: false) { [weak self] result in
|
|||
|
|
// switch result {
|
|||
|
|
// case let .success(model):
|
|||
|
|
// self?.appVersion = model
|
|||
|
|
// block?(model)
|
|||
|
|
// break
|
|||
|
|
// case .failure:
|
|||
|
|
// break
|
|||
|
|
// }
|
|||
|
|
// }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public func findLocaliezedNameBy(code: String) -> String? {
|
|||
|
|
// for per in langNameCodes {
|
|||
|
|
// if per.langCode == code {
|
|||
|
|
// return per.codeName
|
|||
|
|
// }
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static func syncSystemLanguage() {
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 多语言适配
|
|||
|
|
static func syncAppLanuage(lan: Languages, completion: ((_ result: Bool) -> Void)?) {
|
|||
|
|
// MeProvider.request(.updateLanguage(lang: lan.rawValue), modelType: String.self, autoShowErrMsg: false) { result in
|
|||
|
|
// switch result {
|
|||
|
|
// case .success:
|
|||
|
|
// completion?(true)
|
|||
|
|
// break
|
|||
|
|
// case .failure:
|
|||
|
|
// completion?(false)
|
|||
|
|
// break
|
|||
|
|
// }
|
|||
|
|
// }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 通过regionCode来决定国家显示名称
|
|||
|
|
static func getLocalizedCountryName(localeIdentifier: String?) -> String {
|
|||
|
|
guard let identi = localeIdentifier else { return "" }
|
|||
|
|
|
|||
|
|
var regionCode = "en"
|
|||
|
|
|
|||
|
|
// 获取设备的国家Code
|
|||
|
|
if let currentRegionCode = Locale.current.regionCode {
|
|||
|
|
regionCode = currentRegionCode
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
let locale = Locale(identifier: regionCode)
|
|||
|
|
if let localisedCountryName = locale.localizedString(forRegionCode: identi) {
|
|||
|
|
return localisedCountryName
|
|||
|
|
} else {
|
|||
|
|
dlog("⚠️无法localize国家:\(identi)")
|
|||
|
|
return ""
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static func getLocalizedCountryNameByPreferLan(localeIdentifier: String?) -> String {
|
|||
|
|
guard let identi = localeIdentifier else { return "" }
|
|||
|
|
|
|||
|
|
guard let lan = Languages.preferedLans.first else { return "" }
|
|||
|
|
let locale = Locale(identifier: Languages.regionCode(lan: lan))
|
|||
|
|
|
|||
|
|
if let localisedCountryName = locale.localizedString(forRegionCode: identi) {
|
|||
|
|
return localisedCountryName
|
|||
|
|
} else {
|
|||
|
|
dlog("Languages Prefer lan 's locale country name get failed ❌:\(identi) 采用备选方案根据Locale.current来获取")
|
|||
|
|
return getLocalizedCountryName(localeIdentifier: localeIdentifier)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// MARK: - helper.
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
extension CLTool {
|
|||
|
|
static func idfaSetupReport() {
|
|||
|
|
if #available(iOS 14, *) {
|
|||
|
|
ATTrackingManager.requestTrackingAuthorization { status in
|
|||
|
|
switch status {
|
|||
|
|
case .denied:
|
|||
|
|
debugPrint("【IDFA】用户拒绝")
|
|||
|
|
break
|
|||
|
|
case .authorized:
|
|||
|
|
debugPrint("【IDFA】用户允许:❇️IDFA: \(ASIdentifierManager.shared().advertisingIdentifier.uuidString)❇️")
|
|||
|
|
CLTool.tryReportIDFA()
|
|||
|
|
break
|
|||
|
|
case .notDetermined:
|
|||
|
|
debugPrint("【IDFA】用户没有选择")
|
|||
|
|
default:
|
|||
|
|
break
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
// iOS13及之前版本,继续用以前的方式
|
|||
|
|
if ASIdentifierManager.shared().isAdvertisingTrackingEnabled {
|
|||
|
|
// debugPrint("可以获取:\(ASIdentifierManager.shared().advertisingIdentifier.uuidString)")
|
|||
|
|
CLTool.tryReportIDFA()
|
|||
|
|
} else {
|
|||
|
|
debugPrint("【IDFA】用户未打开IDFA开关")
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fileprivate static func tryReportIDFA() {
|
|||
|
|
let str = ASIdentifierManager.shared().advertisingIdentifier.uuidString
|
|||
|
|
if str.contains("0000-0000-0000") || str.count == 0 {
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if let isSubmmited = AppCache.fetchCache(key: CacheKey.boolIdfaSubmmited.rawValue, type: Bool.self), isSubmmited == true {
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ComplexProvider.request(.reportIDFA(str: str), modelType: String.self, autoShowErrMsg: false) { result in
|
|||
|
|
// switch result {
|
|||
|
|
// case let .success(model):
|
|||
|
|
// dlog(model)
|
|||
|
|
// AppCache.cache(key: CacheKey.boolIdfaSubmmited.rawValue, value: true)
|
|||
|
|
// break
|
|||
|
|
// case .failure:
|
|||
|
|
// break
|
|||
|
|
// }
|
|||
|
|
// }
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// MARK: Sandbox
|
|||
|
|
|
|||
|
|
extension CLTool{
|
|||
|
|
static func m4aFileToBase64(fileURL: URL?) -> String? {
|
|||
|
|
guard let fileURL = fileURL else {
|
|||
|
|
dlog("文件 URL 为空")
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
do {
|
|||
|
|
let data = try Data(contentsOf: fileURL)
|
|||
|
|
let base64String = data.base64EncodedString()
|
|||
|
|
return base64String
|
|||
|
|
} catch {
|
|||
|
|
dlog("读取或转换失败: \(error)")
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|