AppCheckVersion.swift 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. //
  2. // CheckVersion.swift
  3. // WisdomCampusApk
  4. //
  5. // Created by 方楚豪 on 2022/1/20.
  6. //
  7. import UIKit
  8. import MMKV
  9. public func XWLog<T>(_ message : T, file : String = #file, lineNumber : Int = #line) {
  10. #if DEBUG
  11. let fileName = (file as NSString).lastPathComponent
  12. print("[\(fileName):line:\(lineNumber)]- \(message)")
  13. #endif
  14. }
  15. public class AppCheckVersion: NSObject {
  16. /// 检查 app 是否需要去 AppStore 做版本更新
  17. ///
  18. /// - Parameters:
  19. /// - appId: appId
  20. /// - completion: completion != nil时,显示自定义 view;completion == nil时,直接显示弹出框(显示API 请求内容)
  21. public class func checkVersion(_ appId: String, _ completion: ((_ dict: [String: Any]) -> ())?) {
  22. if completion == nil {
  23. requestAPI(appId) { (responseDict) in
  24. let message = responseDict["releaseNotes"] as? String ?? ""
  25. let alertContent = "\(message)\n\n是否前往 AppStore 更新版本?"
  26. let trackViewUrlString = responseDict["trackViewUrl"] as? String
  27. let hasIgnore:Bool = MMKV.default()!.bool(forKey: ConstantVC.HAS_IGNORE)
  28. if !hasIgnore {
  29. UIAlertController.alertTip(alertContent, trackViewUrlString)
  30. }
  31. }
  32. } else {
  33. requestAPI(appId, completion: completion)
  34. }
  35. }
  36. class func requestAPI(_ appId: String, completion: ((_ dict: [String: Any]) -> ())?) {
  37. let kItunesURL = "https://itunes.apple.com/cn/lookup?id=\(appId)"
  38. XWLog(kItunesURL)
  39. guard let url = URL(string: kItunesURL) else {
  40. XWLog("\(kItunesURL) is wrong.")
  41. return
  42. }
  43. var request:URLRequest = URLRequest.init(url: url)
  44. request.httpMethod = "POST"
  45. let dataTask = URLSession.shared.dataTask( with: request) {(responseData, response, error) in
  46. guard let data = responseData else {
  47. XWLog("response data is nil.")
  48. return
  49. }
  50. do {
  51. let dict = try JSONSerialization.jsonObject(with: data, options: .mutableLeaves) as! [String: Any]
  52. XWLog(dict)
  53. guard let resultsArray = dict["results"] else {
  54. XWLog("results dictionary is nil.")
  55. return
  56. }
  57. let results = resultsArray as! [[String: Any]]
  58. if results.count > 0 {
  59. let responseDict = results.first ?? [:]
  60. let currentBundleShortVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? ""
  61. let lastVersion = responseDict["version"] as? String ?? ""
  62. /// to update
  63. if currentBundleShortVersion.compare(lastVersion) == .orderedAscending {
  64. // 忽略此版本后,如果APP又更新了一个版本,则不忽略
  65. var appStoreVersion = "5.0.0"
  66. if MMKV.default()!.contains(key: ConstantVC.APP_STORE_VERSION) {
  67. appStoreVersion = MMKV.default()!.string(forKey: ConstantVC.APP_STORE_VERSION)!
  68. }
  69. if appStoreVersion != lastVersion {
  70. MMKV.default()?.set(false, forKey: ConstantVC.HAS_IGNORE)
  71. }
  72. MMKV.default()?.set(true, forKey: ConstantVC.HAS_NEW_VERSION)
  73. DispatchQueue.main.async {
  74. completion?(responseDict)
  75. }
  76. }else {
  77. MMKV.default()?.set(false, forKey: ConstantVC.HAS_NEW_VERSION)
  78. }
  79. MMKV.default()?.set(currentBundleShortVersion, forKey: ConstantVC.APP_VERSION)
  80. MMKV.default()?.set(lastVersion, forKey: ConstantVC.APP_STORE_VERSION)
  81. }
  82. } catch {
  83. XWLog(error)
  84. }
  85. }
  86. dataTask.resume()
  87. }
  88. }
  89. private var kContentLabKey = ""
  90. public extension UIAlertController {
  91. var contentLab: UILabel? {
  92. get {
  93. return objc_getAssociatedObject(self, &kContentLabKey) as? UILabel
  94. }
  95. set(newValue) {
  96. objc_setAssociatedObject(self, &kContentLabKey, newValue, .OBJC_ASSOCIATION_RETAIN)
  97. }
  98. }
  99. class func alertTip(_ contentString: String?, _ trackViewUrlString: String?) {
  100. guard let content = contentString,
  101. let trackViewUrlStr = trackViewUrlString,
  102. let appStoreURL = URL(string: trackViewUrlStr)
  103. else {
  104. return
  105. }
  106. let alertVC = UIAlertController(title: "更新", message: content, preferredStyle: .alert)
  107. let action = UIAlertAction(title: "前往", style: .default) { (action) in
  108. if UIApplication.shared.canOpenURL(appStoreURL) {
  109. if #available(iOS 10.0, *) {
  110. UIApplication.shared.open(appStoreURL, options: [:], completionHandler: nil)
  111. } else {
  112. // Fallback on earlier versions
  113. UIApplication.shared.openURL(appStoreURL)
  114. }
  115. }
  116. }
  117. alertVC.addAction(action)
  118. let action2 = UIAlertAction(title: "忽略此版本", style: .cancel) { (action) in
  119. MMKV.default()?.set(true, forKey: ConstantVC.HAS_IGNORE)
  120. }
  121. alertVC.addAction(action2)
  122. setContentLabAlignment(alertVC)
  123. let keyWindow = UIApplication.shared.connectedScenes
  124. .filter({$0.activationState == .foregroundActive})
  125. .map({$0 as? UIWindowScene})
  126. .compactMap({$0})
  127. .first?.windows
  128. .filter({$0.isKeyWindow}).first
  129. keyWindow?.rootViewController?.present(alertVC, animated: true, completion: nil)
  130. }
  131. class func alertPayTip(_ contentString: String?, _ trackViewUrlString: String?) {
  132. guard let content = contentString,
  133. let trackViewUrlStr = trackViewUrlString,
  134. let appStoreURL = URL(string: trackViewUrlStr)
  135. else {
  136. return
  137. }
  138. let alertVC = UIAlertController(title: "提示", message: content, preferredStyle: .alert)
  139. let action = UIAlertAction(title: "前往", style: .default) { (action) in
  140. if UIApplication.shared.canOpenURL(appStoreURL) {
  141. if #available(iOS 10.0, *) {
  142. UIApplication.shared.open(appStoreURL, options: [:], completionHandler: nil)
  143. } else {
  144. // Fallback on earlier versions
  145. UIApplication.shared.openURL(appStoreURL)
  146. }
  147. }
  148. }
  149. alertVC.addAction(action)
  150. alertVC.addAction(UIAlertAction(title: "取消", style: .cancel, handler: nil))
  151. setContentLabAlignment(alertVC)
  152. UIApplication.shared.keyWindow?.rootViewController?.present(alertVC, animated: true, completion: nil)
  153. }
  154. class func getLabs(_ view: UIView, _ alertVC: UIAlertController) {
  155. var isExist = false
  156. let subviews = view.subviews
  157. for v in subviews {
  158. if v.isKind(of: UILabel.self) {
  159. let lab = v as! UILabel
  160. if lab.text == (alertVC.message ?? "") {
  161. isExist = true
  162. alertVC.contentLab = lab
  163. break
  164. }
  165. }
  166. }
  167. if !isExist && subviews.count > 0 {
  168. getLabs(subviews.first ?? UIView(), alertVC)
  169. }
  170. }
  171. class func setContentLabAlignment(_ alertVC: UIAlertController) {
  172. getLabs(alertVC.view, alertVC)
  173. alertVC.contentLab?.textAlignment = .left
  174. }
  175. }