// // KMAdvertisementManager.swift // KMAdvertisement // // Created by lizhe on 2022/11/23. // 广告管理 @objcMembers open class KMAdvertisementManager: NSObject { //单例 @objc public static let manager = KMAdvertisementManager() @objc public var configuration: KMAdvertisementConfig = KMAdvertisementConfig() var info: KMAdvertisementInfo = KMAdvertisementInfo() var infoDict: NSDictionary = NSDictionary() /** @abstract 测试模式,默认为false */ @objc public var debug: Bool = false /** @abstract 初始化数据 @param appID 产品名称 @param subscribeType 订阅状态,可单独在configuration设置 @param platform 平台 @return */ @objc public func initConfig(appName: KMAdvertisementAppNameType, subscribeType:KMAdvertisementSubscribeType, platform: KMAdvertisementPlatformType) { configuration.initParameters(appName: appName, subscribeType: subscribeType, platform: platform) } private class InternalImplementation { fileprivate var privateProperty: String = "Hidden" fileprivate func internalMethod() { // 实现细节 } } private let internalImplementation = InternalImplementation() public func publicMethod() { // 使用内部实现 internalImplementation.internalMethod() } } extension KMAdvertisementManager { //MARK: request /** @abstract 获取数据 @param data 传入参数 类型为KMAdvertisementModel @return */ @objc public func fetchData(completion: @escaping (_ data: KMAdvertisementInfo?, _ error:Error?) -> Void) -> Void { self.fetchDataWithResponseObject { data, responseObject, error in if completion != nil { completion(data, error) } } } @objc public func fetchDataWithResponseObject(completion:@escaping (_ data: KMAdvertisementInfo?, _ responseObject: AnyObject? , _ error:Error?) -> Void) -> Void { print("开始获取数据") var version: String = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString").debugDescription if (version.count == 0) { version = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion").debugDescription version = version.replacingOccurrences(of: ".", with: "") } let urlString = configuration.activityBaseURL() + "/api/advertise-new" let params: [String:Any] = ["app_name": configuration.appName.string(), "app_version": version] //先拿缓存数据 再请求新数据 // let cacheData = KMAdvertisementCache.default.readData() // if cacheData.count != 0 { // for model in cacheData { // let jsonString: String = (model["detail"] as? String) ?? "" // let jsonData: Data = jsonString.data(using: .utf8)! // let dict = try?JSONSerialization.jsonObject(with: jsonData) // infoDict = dict as! NSDictionary // } // self.parseData(data: cacheData, isNeedLocalComparison: true) { result in // if result.count != 0 { // info = result.first! // completion(result.first, nil, nil) // } // } // } unowned let weakSelf = self KMAdvertisementRequestServer.requestServer.request(urlString: urlString, method: "GET", params: params) { [self] task, responseObject, error in print("正在获取数据") if (error == nil && responseObject != nil) { let array = responseObject?["list"] ?? [] if array != nil { //解析数据 print("开始解析数据") for model in array as! [NSDictionary] { let jsonString: String = (model["detail"] as? String) ?? "" let jsonData: Data = jsonString.data(using: .utf8)! let dict = try?JSONSerialization.jsonObject(with: jsonData) infoDict = dict as! NSDictionary } weakSelf.parseData(data: array as! [NSDictionary], isNeedLocalComparison: true) { data in print("数据处理完毕") if data.count != 0 { info = data.first! completion(data.first, responseObject, nil) } } } else { print("解析数据失败array") completion(nil, responseObject, error) } } else { print("解析数据失败数据不存在") completion(nil, responseObject, error) } } } } extension KMAdvertisementManager { //MARK: data /** @abstract 解析数据 @param data 传入参数 NSDictionary @param isNeedLocalComparison 是否需要对比本地版本,如果不一样将会刷新 @return KMAdvertisementModel */ public func parseData(data: [NSDictionary], isNeedLocalComparison: Bool ,completion:(_ result: [KMAdvertisementInfo]) -> Void) -> Void { //获取缓存数据 var isNeedSave = false let cacheData = KMAdvertisementCache.default.readData() var resultArray:[KMAdvertisementInfo] = [] for model in data { if (isNeedLocalComparison) { if (self.allowLoadData(data: model)) { let jsonString: String = (model["detail"] as? String) ?? "" let jsonData: Data = jsonString.data(using: .utf8)! let dict = try?JSONSerialization.jsonObject(with: jsonData) let decoder = JSONDecoder() // decoder.dataDecodingStrategy = .base64 // decoder.keyDecodingStrategy = .convertFromSnakeCase //带下划线命名 decoder.nonConformingFloatDecodingStrategy = .convertFromString(positiveInfinity: "+∞", negativeInfinity: "-∞", nan: "NaN") #if DEBUG print(dict) //MARK: 测试使用 var advertisementModel = try! decoder.decode(KMAdvertisementInfo.self, from: jsonData) if (self.allowLoadContentData(data: advertisementModel)) { resultArray.append(self.allowLoadItemData(advertisementModel)) isNeedSave = true } #else // MARK: 此处try 使用 ? ,如果数据出问题 advertisementModel将无参数, 测试时使用! var advertisementModel = try? decoder.decode(KMAdvertisementInfo.self, from: jsonData) if (advertisementModel != nil) { if (self.allowLoadContentData(data: advertisementModel!)) { resultArray.append(self.allowLoadItemData(advertisementModel!)) isNeedSave = true } } #endif } } } if isNeedSave && isNeedLocalComparison { KMAdvertisementCache.default.saveData(data: data) print("已更新本地数据") } else { print("不需要更新本地数据") } completion(resultArray) } func allowLoadData(data: NSDictionary) -> Bool { var result = false let status = (data["status"] as? Int) ?? 0 let app_name: String = data["app_name"] as? String ?? "" if (status == 1 && app_name == configuration.appName.string()) { result = true } return result } func allowLoadContentData(data: KMAdvertisementInfo) -> Bool { var result = true return result } //过滤item是否显示 func allowLoadItemData(_ data: KMAdvertisementInfo) -> KMAdvertisementInfo { let advertisement = data.advertisement advertisement?.content = self.canShow(data: (advertisement?.content)!) data.advertisement = advertisement let recommondContent = data.recommondContent let recommondContentOther = recommondContent?.recommondContentOther let recommondContentPDFPro = recommondContent?.recommondContentPDFPro recommondContentOther?.content = self.canShow(data: (recommondContentOther?.content)!) recommondContentPDFPro?.content = self.canShow(data: (recommondContentPDFPro?.content)!) recommondContent?.recommondContentOther = recommondContentOther recommondContent?.recommondContentPDFPro = recommondContentPDFPro data.recommondContent = recommondContent let topRightInfoContent = data.topRightInfoContent if let content = topRightInfoContent?.content { topRightInfoContent?.content = self.canShow(data: content) } let loginViewContent = data.loginViewContent if let content = loginViewContent?.content { loginViewContent?.content = self.canShow(data: content) } let userViewInfoContent = data.userViewInfoContent if let content = userViewInfoContent?.content { userViewInfoContent?.content = self.canShow(data: content) } return data; } func canShow(data: [KMAdvertisementItemInfo]) -> [KMAdvertisementItemInfo] { var dataArray: [KMAdvertisementItemInfo] = [] for item in data { let currentTime = Int(NSDate.init().timeIntervalSince1970 * 1000) if item.show == "1" && currentTime > Int(item.startTime ?? "0") ?? currentTime && currentTime < Int(item.endTime ?? "0") ?? currentTime { var canAdd = true if item.subscriptionType == "1" { if (IAPProductsManager.default().isAvailableAllFunction()) { canAdd = false } } else if item.subscriptionType == "2" { if (IAPProductsManager.default().isAvailableAllFunction() == false) { canAdd = false } } if canAdd { dataArray.append(item) } } } return dataArray } //获取本地版本号 func getLocalVersion() -> String { var localVersion = "" if let v: String = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String { localVersion = v } return localVersion } func compareVersion(nowVersion: String, newVersion: String) -> Bool { let nowArray = nowVersion.split(separator: ".") let newArray = newVersion.split(separator: ".") let big = nowArray.count > newArray.count ? newArray.count : nowArray.count if big != 0 { for index in 0...big - 1 { let first = nowArray[index] let second = newArray[index] if Int(first)! < Int(second)! { return true } if index == big - 1 { if Int(first)! <= Int(second)! { return true } } } } else { return true } return false } } extension KMAdvertisementManager { static func checkAdvertisementValid(_ info: KMAdvertisementItemInfo) -> Bool { #if DEBUG UserDefaults.standard.removeObject(forKey: info.version ?? "") #endif if UserDefaults.standard.object(forKey: info.version ?? "") != nil { return false } if (info.show == nil) { return false } let currentTime = Int(NSDate.init().timeIntervalSince1970 * 1000) if currentTime > Int(info.startTime ?? "0") ?? currentTime && currentTime < Int(info.endTime ?? "0") ?? currentTime { } else { return false } if info.subscriptionType == "1" { if IAPProductsManager.default().isAvailableAllFunction() == true { return false } } else if info.subscriptionType == "2" { if !IAPProductsManager.default().isAvailableAllFunction() { return true } } return true } }