import Cocoa import SystemConfiguration enum KMAdsState: Int { case none = 0 case initialize case requestOk case requestFail case show case finish } //最后加载完广告的日期 let kLastLoadingDate = "LastLoadingDate" //今天加载的频次 let kTodayLoadingNumber = "TodayLoadingNumber" //评价后最后加载完广告的日期 let kLastLoadingDateAfter = "LastLoadingDateAfter" //评价后今天加载的频次 let kTodayLoadingNumberAfter = "TodayLoadingNumberAfter" let kADViewWithTag = 1000 class KMAdsManager: NSObject { private var adViews: [KMAdsWebView] = [] private var isEnableShowAds: Bool = true private var appFreeTimeAdsCount: Int = 0 private var adsState: KMAdsState = .none private var appFreeAfterTimeAdsCount: Int = 0 static let defaultManager = KMAdsManager() private override init() { super.init() adViews = [] isEnableShowAds = true appFreeTimeAdsCount = UserDefaults.standard.integer(forKey: "KMEvaluateBeforeCloseAdsNumbersKey") appFreeAfterTimeAdsCount = UserDefaults.standard.integer(forKey: "KMEvaluateAfterCloseAdsNumbersKey") adsState = .none } func beginSheetModal(for view: NSView, directions: KMADViewDirections, animated: Bool, completionHandler handler: @escaping (Int) -> Void) -> Bool { return beginSheetModalForView(view, directions: directions, adPosY: 30.0, animated: animated, completionHandler: handler) } func beginSheetModalForView(_ view: NSView, directions: KMADViewDirections, adPosY posY: CGFloat, animated: Bool, completionHandler handler: @escaping (Int) -> Void) -> Bool { if let adView = self.adView(at: view) { adView.removeFromSuperview() adView.adPosY = posY view.addSubview(adView) if adView.adsInfo == nil { self.refreshDataInfo(with: adView) } else { adView.reloadData() } return false } if !isValidLastShowAds() { return false } if !checkTheDate() { return false } if !checkNetworkAvailable() { return false } switch adsState { case .none, .finish: adsState = .show default: break } let adView = KMAdsWebView() adView.adPosY = posY adView.sortAdsData() adView.adDelegate = self // adView.tag = kADViewWithTag adView.beginSheetModalForView(view: view, directions: directions, animated: animated, completionHandler: handler) adViews.append(adView) self.refreshDataInfo(with: adView) return true } func refreshDataInfo(with adView: KMAdsWebView) { if KMAdsInfoManager.shareInstance.adsInfoArrM != nil { if KMAdsInfoManager.shareInstance.adsInfoArrM.count > 0 { let adsInfo = KMAdsInfoManager.shareInstance.getRandomAdsInfo() if adsInfo?.show == true { adView.adsInfo = adsInfo adView.reloadData() } else { adView.isHidden = true } } else { adView.isHidden = true } } } func adView(at view: NSView) -> KMAdsWebView? { guard let adView = adViews.first else { return nil } // guard let adView = view.viewWithTag(kADViewWithTag) as? KMAdsWebView else { // return nil // } return adView } func dismissSheetModal(for view: NSView) { if let adView = adViews.first { adViews.removeAll { $0 == adView } adView.stopLoading() adView.removeFromSuperview() } // if let adView = view.viewWithTag(kADViewWithTag) as? KMAdsWebView { // adViews.removeAll { $0 == adView } // adView.removeFromSuperview() // } adsState = .finish updateShowAdsDate() } func showFreeTimeAdsInfo() { print("KMPurchaseCompareWindowController") // KMPurchaseCompareWindowController.sharedInstance().showWindow(nil) } func checkNetworkAvailable() -> Bool { guard let reachability = SCNetworkReachabilityCreateWithName(nil, "www.apple.com") else { return false } var flags: SCNetworkReachabilityFlags = SCNetworkReachabilityFlags(rawValue: 0) if SCNetworkReachabilityGetFlags(reachability, &flags) { let isDataSourceAvailable = flags.contains(.reachable) && !flags.contains(.connectionRequired) return isDataSourceAvailable } return false } func refreshLoadingDate() { var todayLoadingNumber = 0 if !UserDefaults.standard.bool(forKey: "kUserHaveClickRateUsKey") { todayLoadingNumber = UserDefaults.standard.integer(forKey: kTodayLoadingNumber) todayLoadingNumber += 1 UserDefaults.standard.set(todayLoadingNumber, forKey: kTodayLoadingNumber) let date = Date() let formatter = DateFormatter() formatter.dateFormat = "yyyy-MM-dd" let str = formatter.string(from: date) UserDefaults.standard.set(str, forKey: kLastLoadingDate) } else { todayLoadingNumber = UserDefaults.standard.integer(forKey: kTodayLoadingNumberAfter) todayLoadingNumber += 1 UserDefaults.standard.set(todayLoadingNumber, forKey: kTodayLoadingNumberAfter) let date = Date() let formatter = DateFormatter() formatter.dateFormat = "yyyy-MM-dd" let str = formatter.string(from: date) UserDefaults.standard.set(str, forKey: kLastLoadingDateAfter) } } func checkTheDate() -> Bool { if !UserDefaults.standard.bool(forKey: "kUserHaveClickRateUsKey") { let dateToday = Date() let formatter = DateFormatter() formatter.dateFormat = "yyyy-MM-dd" let str = formatter.string(from: dateToday) let string = UserDefaults.standard.string(forKey: kLastLoadingDate) ?? "1990-01-01" let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd" guard let lastDate = dateFormatter.date(from: string) else { return false } let isToday = Calendar.current.isDateInToday(lastDate) if !isToday { UserDefaults.standard.set(0, forKey: kTodayLoadingNumber) return true } else { var todayLoadingNumber = 0 if UserDefaults.standard.integer(forKey: kTodayLoadingNumber) != 0 { todayLoadingNumber = UserDefaults.standard.integer(forKey: kTodayLoadingNumber) } if todayLoadingNumber >= KMKdanRemoteConfig.remoteConfig.refreshAdsRate() { return false } } } else { let dateToday = Date() let formatter = DateFormatter() formatter.dateFormat = "yyyy-MM-dd" let str = formatter.string(from: dateToday) let string = UserDefaults.standard.string(forKey: kLastLoadingDateAfter) ?? str let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd" guard let lastDate = dateFormatter.date(from: string) else { return false } let isToday = Calendar.current.isDateInToday(lastDate) if !isToday { UserDefaults.standard.set(0, forKey: kTodayLoadingNumberAfter) return true } else { var todayLoadingNumber = 0 if UserDefaults.standard.integer(forKey: kTodayLoadingNumberAfter) != 0 { todayLoadingNumber = UserDefaults.standard.integer(forKey: kTodayLoadingNumberAfter) } if todayLoadingNumber >= KMKdanRemoteConfig.remoteConfig.refreshAdsRateEvaluateAfter() { return false } } } return true } func updateShowAdsDate() { let defaults = UserDefaults.standard let format = DateFormatter() format.dateFormat = "yyyy-MM-dd HH:mm:ss ZZZ" let currentDate = Date() let strCurDate = format.string(from: currentDate) defaults.setValue(strCurDate, forKey: "km_app_show_ads_date") defaults.synchronize() } func isValidLastShowAds() -> Bool { let defaults = UserDefaults.standard var tAdsFlag = false if let startStr = defaults.string(forKey: "km_app_show_ads_date") { let format = DateFormatter() format.dateFormat = "yyyy-MM-dd HH:mm:ss ZZZ" guard let startD = format.date(from: startStr) else { return false } var closeDate = 0 if !UserDefaults.standard.bool(forKey: "kUserHaveClickRateUsKey") { closeDate = KMKdanRemoteConfig.remoteConfig.closeIntervalDate() } else { closeDate = KMKdanRemoteConfig.remoteConfig.closeIntervalDateEvaluateAfter() } let tCurDate = Date(timeIntervalSinceNow: TimeInterval(-closeDate)) let result = tCurDate.compare(startD) if result == .orderedDescending { tAdsFlag = true } } else { if !UserDefaults.standard.bool(forKey: "kUserHaveClickRateUsKey") { tAdsFlag = KMKdanRemoteConfig.remoteConfig.isDisplayAds() } else { tAdsFlag = KMKdanRemoteConfig.remoteConfig.isDisplayAdsEvaluateAfter() } } return tAdsFlag } } extension KMAdsManager: AdsWebViewDelegate { // MARK: - KMADViewDelegate func kmAdViewClose(_ tView: KMAdsWebView) { for view in self.adViews { view.stopLoading() view.removeFromSuperview() } self.adViews.removeAll() self.adsState = .finish self.updateShowAdsDate() if !UserDefaults.standard.bool(forKey: "kUserHaveClickRateUsKey") { self.appFreeTimeAdsCount = (self.appFreeTimeAdsCount + 1) % KMKdanRemoteConfig.remoteConfig.appEvaluateBeforeAdsCount() UserDefaults.standard.set(self.appFreeTimeAdsCount, forKey: "KMEvaluateBeforeCloseAdsNumbersKey") if 0 == (self.appFreeTimeAdsCount % KMKdanRemoteConfig.remoteConfig.appEvaluateBeforeAdsCount()) { self.showFreeTimeAdsInfo() } } else { self.appFreeAfterTimeAdsCount = (self.appFreeAfterTimeAdsCount + 1) % KMKdanRemoteConfig.remoteConfig.appEvaluateAfterAdsCount() UserDefaults.standard.set(self.appFreeAfterTimeAdsCount, forKey: "KMEvaluateAfterCloseAdsNumbersKey") if 0 == (self.appFreeAfterTimeAdsCount % KMKdanRemoteConfig.remoteConfig.appEvaluateAfterAdsCount()) { self.showFreeTimeAdsInfo() } } } func kmAdViewClicked(_ tView: KMAdsWebView) { for view in self.adViews { view.stopLoading() view.removeFromSuperview() } self.adViews.removeAll() self.adsState = .finish self.updateShowAdsDate() } }