KMAdvertisementManager.swift 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. //
  2. // KMAdvertisementManager.swift
  3. // KMAdvertisement
  4. //
  5. // Created by lizhe on 2022/11/23.
  6. // 广告管理
  7. let KMAdvertisementDidLoadedNotificationName = "KMAdvertisementDidLoadedNotification"
  8. @objcMembers open class KMAdvertisementManager: NSObject {
  9. //单例
  10. @objc public static let manager = KMAdvertisementManager()
  11. @objc public var configuration: KMAdvertisementConfig = KMAdvertisementConfig()
  12. var appClosedCount = 0
  13. var info: KMAdvertisementInfo = KMAdvertisementInfo()
  14. var infoDict: NSDictionary = NSDictionary()
  15. /**
  16. @abstract 测试模式,默认为false
  17. */
  18. @objc public var debug: Bool = false
  19. /**
  20. @abstract 初始化数据
  21. @param appID 产品名称
  22. @param subscribeType 订阅状态,可单独在configuration设置
  23. @param platform 平台
  24. @return
  25. */
  26. @objc public func initConfig(appName: KMAdvertisementAppNameType,
  27. subscribeType:KMAdvertisementSubscribeType,
  28. platform: KMAdvertisementPlatformType) {
  29. configuration.initParameters(appName: appName, subscribeType: subscribeType, platform: platform)
  30. }
  31. private class InternalImplementation {
  32. fileprivate var privateProperty: String = "Hidden"
  33. fileprivate func internalMethod() {
  34. // 实现细节
  35. }
  36. }
  37. private let internalImplementation = InternalImplementation()
  38. public func publicMethod() {
  39. // 使用内部实现
  40. internalImplementation.internalMethod()
  41. }
  42. }
  43. extension KMAdvertisementManager {
  44. //MARK: request
  45. /**
  46. @abstract 获取数据
  47. @param data 传入参数 类型为KMAdvertisementModel
  48. @return
  49. */
  50. @objc public func fetchData(completion: @escaping (_ data: KMAdvertisementInfo?, _ error:Error?) -> Void) -> Void {
  51. self.fetchDataWithResponseObject { data, responseObject, error in
  52. if completion != nil {
  53. completion(data, error)
  54. }
  55. }
  56. }
  57. @objc public func fetchDataWithResponseObject(completion:@escaping (_ data: KMAdvertisementInfo?, _ responseObject: AnyObject? , _ error:Error?) -> Void) -> Void {
  58. print("开始获取数据")
  59. var version: String = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString").debugDescription
  60. if (version.count == 0) {
  61. version = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion").debugDescription
  62. version = version.replacingOccurrences(of: ".", with: "")
  63. }
  64. let urlString = configuration.activityBaseURL() + "/api/advertise-new"
  65. let params: [String:Any] = ["app_name": configuration.appName.string(),
  66. "app_version": version]
  67. //先拿缓存数据 再请求新数据
  68. // let cacheData = KMAdvertisementCache.default.readData()
  69. // if cacheData.count != 0 {
  70. // for model in cacheData {
  71. // let jsonString: String = (model["detail"] as? String) ?? ""
  72. // let jsonData: Data = jsonString.data(using: .utf8)!
  73. // let dict = try?JSONSerialization.jsonObject(with: jsonData)
  74. // infoDict = dict as! NSDictionary
  75. // }
  76. // self.parseData(data: cacheData, isNeedLocalComparison: true) { result in
  77. // if result.count != 0 {
  78. // info = result.first!
  79. // completion(result.first, nil, nil)
  80. // }
  81. // }
  82. // }
  83. unowned let weakSelf = self
  84. KMAdvertisementRequestServer.requestServer.request(urlString: urlString, method: "GET", params: params) { [self] task, responseObject, error in
  85. print("正在获取数据")
  86. if (error == nil && responseObject != nil) {
  87. let array = responseObject?["list"] ?? []
  88. if array != nil {
  89. //解析数据
  90. print("开始解析数据")
  91. for model in array as! [NSDictionary] {
  92. let jsonString: String = (model["detail"] as? String) ?? ""
  93. let jsonData: Data = jsonString.data(using: .utf8)!
  94. let dict = try?JSONSerialization.jsonObject(with: jsonData)
  95. infoDict = dict as! NSDictionary
  96. }
  97. weakSelf.parseData(data: array as! [NSDictionary], isNeedLocalComparison: true) { data in
  98. print("数据处理完毕")
  99. if data.count != 0 {
  100. info = data.first!
  101. completion(data.first, responseObject, nil)
  102. }
  103. }
  104. } else {
  105. print("解析数据失败array")
  106. completion(nil, responseObject, error)
  107. }
  108. } else {
  109. print("解析数据失败数据不存在")
  110. completion(nil, responseObject, error)
  111. }
  112. }
  113. }
  114. }
  115. extension KMAdvertisementManager {
  116. //MARK: data
  117. /**
  118. @abstract 解析数据
  119. @param data 传入参数 NSDictionary
  120. @param isNeedLocalComparison 是否需要对比本地版本,如果不一样将会刷新
  121. @return KMAdvertisementModel
  122. */
  123. public func parseData(data: [NSDictionary], isNeedLocalComparison: Bool ,completion:(_ result: [KMAdvertisementInfo]) -> Void) -> Void {
  124. //获取缓存数据
  125. var isNeedSave = false
  126. let cacheData = KMAdvertisementCache.default.readData()
  127. var resultArray:[KMAdvertisementInfo] = []
  128. for model in data {
  129. if (isNeedLocalComparison) {
  130. if (self.allowLoadData(data: model)) {
  131. let jsonString: String = (model["detail"] as? String) ?? ""
  132. let jsonData: Data = jsonString.data(using: .utf8)!
  133. let dict = try?JSONSerialization.jsonObject(with: jsonData)
  134. let decoder = JSONDecoder()
  135. // decoder.dataDecodingStrategy = .base64
  136. // decoder.keyDecodingStrategy = .convertFromSnakeCase //带下划线命名
  137. decoder.nonConformingFloatDecodingStrategy = .convertFromString(positiveInfinity: "+∞", negativeInfinity: "-∞", nan: "NaN")
  138. #if DEBUG
  139. print(dict)
  140. //MARK: 测试使用
  141. var advertisementModel = try! decoder.decode(KMAdvertisementInfo.self, from: jsonData)
  142. if (self.allowLoadContentData(data: advertisementModel)) {
  143. resultArray.append(self.allowLoadItemData(advertisementModel))
  144. isNeedSave = true
  145. }
  146. #else
  147. // MARK: 此处try 使用 ? ,如果数据出问题 advertisementModel将无参数, 测试时使用!
  148. var advertisementModel = try? decoder.decode(KMAdvertisementInfo.self, from: jsonData)
  149. if (advertisementModel != nil) {
  150. if (self.allowLoadContentData(data: advertisementModel!)) {
  151. resultArray.append(self.allowLoadItemData(advertisementModel!))
  152. isNeedSave = true
  153. }
  154. }
  155. #endif
  156. }
  157. }
  158. }
  159. if isNeedSave && isNeedLocalComparison {
  160. KMAdvertisementCache.default.saveData(data: data)
  161. print("已更新本地数据")
  162. } else {
  163. print("不需要更新本地数据")
  164. }
  165. completion(resultArray)
  166. }
  167. func allowLoadData(data: NSDictionary) -> Bool {
  168. var result = false
  169. let status = (data["status"] as? Int) ?? 0
  170. let app_name: String = data["app_name"] as? String ?? ""
  171. if (status == 1 &&
  172. app_name == configuration.appName.string()) {
  173. result = true
  174. }
  175. return result
  176. }
  177. func allowLoadContentData(data: KMAdvertisementInfo) -> Bool {
  178. var result = true
  179. return result
  180. }
  181. //过滤item是否显示
  182. func allowLoadItemData(_ data: KMAdvertisementInfo) -> KMAdvertisementInfo {
  183. let advertisement = data.advertisement
  184. advertisement?.content = self.canShow(data: (advertisement?.content)!)
  185. data.advertisement = advertisement
  186. let recommondContent = data.recommondContent
  187. let recommondContentOther = recommondContent?.recommondContentOther
  188. let recommondContentPDFPro = recommondContent?.recommondContentPDFPro
  189. recommondContentOther?.content = self.canShow(data: (recommondContentOther?.content)!)
  190. recommondContentPDFPro?.content = self.canShow(data: (recommondContentPDFPro?.content)!)
  191. recommondContent?.recommondContentOther = recommondContentOther
  192. recommondContent?.recommondContentPDFPro = recommondContentPDFPro
  193. data.recommondContent = recommondContent
  194. let topRightInfoContent = data.topRightInfoContent
  195. if let content = topRightInfoContent?.content {
  196. topRightInfoContent?.content = self.canShow(data: content)
  197. }
  198. let loginViewContent = data.loginViewContent
  199. if let content = loginViewContent?.content {
  200. loginViewContent?.content = self.canShow(data: content)
  201. }
  202. let userViewInfoContent = data.userViewInfoContent
  203. if let content = userViewInfoContent?.content {
  204. userViewInfoContent?.content = self.canShow(data: content)
  205. }
  206. return data;
  207. }
  208. func canShow(data: [KMAdvertisementItemInfo]) -> [KMAdvertisementItemInfo] {
  209. var dataArray: [KMAdvertisementItemInfo] = []
  210. for item in data {
  211. let currentTime = Int(NSDate.init().timeIntervalSince1970 * 1000)
  212. if item.show == "1" &&
  213. currentTime > Int(item.startTime ?? "0") ?? currentTime &&
  214. currentTime < Int(item.endTime ?? "0") ?? currentTime {
  215. var canAdd = true
  216. if item.subscriptionType == "1" {
  217. if (KMMemberInfo.shared.isMemberAllFunction == true) {
  218. canAdd = false
  219. }
  220. } else if item.subscriptionType == "2" {
  221. if (KMMemberInfo.shared.isMemberAllFunction == false) {
  222. canAdd = false
  223. }
  224. }
  225. if canAdd {
  226. dataArray.append(item)
  227. }
  228. }
  229. }
  230. return dataArray
  231. }
  232. //获取本地版本号
  233. func getLocalVersion() -> String {
  234. var localVersion = ""
  235. if let v: String = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String {
  236. localVersion = v
  237. }
  238. return localVersion
  239. }
  240. func compareVersion(nowVersion: String, newVersion: String) -> Bool {
  241. let nowArray = nowVersion.split(separator: ".")
  242. let newArray = newVersion.split(separator: ".")
  243. let big = nowArray.count > newArray.count ? newArray.count : nowArray.count
  244. if big != 0 {
  245. for index in 0...big - 1 {
  246. let first = nowArray[index]
  247. let second = newArray[index]
  248. if Int(first)! < Int(second)! {
  249. return true
  250. }
  251. if index == big - 1 {
  252. if Int(first)! <= Int(second)! {
  253. return true
  254. }
  255. }
  256. }
  257. } else {
  258. return true
  259. }
  260. return false
  261. }
  262. }
  263. extension KMAdvertisementManager {
  264. static func checkAdvertisementValid(_ info: KMAdvertisementItemInfo) -> Bool {
  265. #if DEBUG
  266. UserDefaults.standard.removeObject(forKey: info.version ?? "")
  267. #endif
  268. if UserDefaults.standard.object(forKey: info.version ?? "") != nil {
  269. return false
  270. }
  271. if (info.show == nil) {
  272. return false
  273. }
  274. let currentTime = Int(NSDate.init().timeIntervalSince1970 * 1000)
  275. if currentTime > Int(info.startTime ?? "0") ?? currentTime &&
  276. currentTime < Int(info.endTime ?? "0") ?? currentTime {
  277. } else {
  278. return false
  279. }
  280. if info.subscriptionType == "1" {
  281. if KMMemberInfo.shared.isMemberAllFunction == true {
  282. return false
  283. }
  284. } else if info.subscriptionType == "2" {
  285. if !KMMemberInfo.shared.isMemberAllFunction {
  286. return true
  287. }
  288. }
  289. return true
  290. }
  291. }