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 private var timer: Timer? static let defaultManager = KMAdsManager() var didClosed = false private override init() { super.init() adViews = [] isEnableShowAds = true appFreeTimeAdsCount = UserDefaults.standard.integer(forKey: "KMEvaluateBeforeCloseAdsNumbersKey") appFreeAfterTimeAdsCount = UserDefaults.standard.integer(forKey: "KMEvaluateAfterCloseAdsNumbersKey") adsState = .none timer = Timer.scheduledTimer(timeInterval: TimeInterval(8), target: self, selector: #selector(adsWebView_Switch), userInfo: nil, repeats: true) RunLoop.current.add(timer!, forMode: .common) } 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 self.didClosed { return false } switch adsState { case .none, .finish: adsState = .show default: break } let adView = KMAdsWebView() adView.adPosY = posY adView.adDelegate = self adView.beginSheetModalForView(view: view, directions: directions, animated: animated, completionHandler: handler) adViews.append(adView) self.refreshDataInfo(with: adView) return true } func invalidTimer() { if timer != nil { timer?.invalidate() timer = nil } } 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 } return adView } func dismissSheetModal(for view: NSView) { if let adView = adViews.first { adViews.removeAll { $0 == adView } adView.removeFromSuperview() } adsState = .finish } func showFreeTimeAdsInfo() { print("KMPurchaseCompareWindowController") } 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 } @objc func adsWebView_Switch() { DispatchQueue.main.async { if self.adViews.count > 1 { if let adView = self.adViews.first { self.refreshDataInfo(with: adView) } } else { self.invalidTimer() } } } } extension KMAdsManager: AdsWebViewDelegate { // MARK: - KMADViewDelegate func kmAdViewClose(_ tView: KMAdsWebView) { for view in self.adViews { 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() } } self.didClosed = true self.invalidTimer() } func kmAdViewClicked(_ tView: KMAdsWebView) { for view in self.adViews { view.removeFromSuperview() } self.adViews.removeAll() self.adsState = .finish self.updateShowAdsDate() self.didClosed = true self.invalidTimer() } }