362 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Swift
		
	
	
			
		
		
	
	
			362 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Swift
		
	
	
| // AdsEngineManager.swift
 | |
| // Manages all ad engines
 | |
| // Corresponds to AdsEngineManager.kt in Android implementation
 | |
| 
 | |
| import Foundation
 | |
| import UIKit
 | |
| 
 | |
| class AdsEngineManager {
 | |
|     
 | |
|     private let viewController: UIViewController
 | |
|     
 | |
|     private var interstitialAdEngines: [Int: InterstitialAdEngine] = [:]
 | |
|     private var rewardedAdEngines: [Int: RewardedAdEngine] = [:]
 | |
|     private var bannerAdEngines: [Int: BannerAdEngine] = [:]
 | |
|     private var mrecAdEngines: [Int: MRecAdEngine] = [:]
 | |
|     
 | |
|     private var supportedAdsSdk: [AdPlatform: GuruAdsSdk] = [:]
 | |
|     
 | |
|     init(viewController: UIViewController) {
 | |
|         self.viewController = viewController
 | |
|     }
 | |
|     
 | |
|     // MARK: - Logging
 | |
|     
 | |
|     private func logInfo(_ message: String) {
 | |
|         Logger.i(tag: "StrategyManager", message: message)
 | |
|     }
 | |
|     
 | |
|     private func logError(_ message: String, error: Error? = nil) {
 | |
|         Logger.e(tag: "StrategyManager", message: message)
 | |
|     }
 | |
|     
 | |
|     // MARK: - SDK Management
 | |
|     
 | |
|     internal func addAdsSdk(_ adsSdk: GuruAdsSdk) {
 | |
|         supportedAdsSdk[adsSdk.adPlatform] = adsSdk
 | |
|     }
 | |
|     
 | |
|     private func getAdsSdk(adPlatform: AdPlatform) -> GuruAdsSdk? {
 | |
|         return supportedAdsSdk[adPlatform]
 | |
|     }
 | |
|     
 | |
|     // MARK: - Interstitial Engine Methods
 | |
|     
 | |
|     private func createDefaultInterstitialAdEngine(
 | |
|         id: Int,
 | |
|         config: DefaultInterstitialConfig
 | |
|     ) -> DefaultInterstitialAdEngine? {
 | |
|         if let adSdk = getAdsSdk(adPlatform: AdPlatform.fromName(config.adPlatform))?.obtainInterstitialAd(
 | |
|             adConfig: AdConfig(
 | |
|                 engineId: id,
 | |
|                 adUnitId: config.adUnitId,
 | |
|                 adAmazonSlotId: config.adAmazonSlotId
 | |
|             )
 | |
|         ) {
 | |
|            return DefaultInterstitialAdEngine(viewController: viewController, id: id, ad: adSdk)
 | |
|         } else {
 | |
|             return nil;
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     private func createMabInterstitialEngine(
 | |
|         id: Int,
 | |
|         faUnitId: String,
 | |
|         config: MabInterstitialConfig
 | |
|     ) -> MabInterstitialEngine {
 | |
|         return MabInterstitialEngine(viewController: viewController, id: id, faUnitId: faUnitId, mabConfig: config) {
 | |
|             [weak self] adPlatform, adConfig in
 | |
|             self?.getAdsSdk(adPlatform: adPlatform)?.obtainInterstitialAd(adConfig: adConfig)
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     func getInterstitialAdEngine(id: Int) -> InterstitialAdEngine? {
 | |
|         return interstitialAdEngines[id]
 | |
|     }
 | |
|     
 | |
|     func createInterstitialAdEngine(adEngineConfig: AdEngineConfig) -> InterstitialAdEngine? {
 | |
|         // Potential hashcode collision
 | |
|         let id = adEngineConfig.hashCode()
 | |
|         logInfo("createInterstitialAdEngine: \(id)")
 | |
|     
 | |
|         
 | |
|         let engine:InterstitialAdEngine? = getInterstitialAdEngine(id: id) ?? {
 | |
|             logInfo("config parsed!, with strategy \(InterstitialStrategy.default.rawValue)")
 | |
|             switch adEngineConfig.strategy {
 | |
|             case InterstitialStrategy.default.rawValue:
 | |
|                 guard let config = try? DefaultInterstitialConfig(adEngineConfig.config) else {
 | |
|                     return nil;
 | |
|                 }
 | |
|                 return createDefaultInterstitialAdEngine(
 | |
|                     id: id,
 | |
|                     config: config
 | |
|                 )
 | |
|             case InterstitialStrategy.mab.rawValue:
 | |
|                 guard let config = try? MabInterstitialConfig(adEngineConfig.config) else {
 | |
|                     return nil;
 | |
|                 }
 | |
|                 return createMabInterstitialEngine(id: id, faUnitId: adEngineConfig.faUnitId, config: config)
 | |
|             default:
 | |
|                 // todo forward compatible
 | |
|                 guard let config = try? DefaultInterstitialConfig(adEngineConfig.config) else {
 | |
|                     return nil;
 | |
|                 }
 | |
|                 return createDefaultInterstitialAdEngine(
 | |
|                     id: id,
 | |
|                     config:config
 | |
|                 )
 | |
|             }
 | |
|         }()
 | |
|         
 | |
|         if let engine = engine {
 | |
|             interstitialAdEngines[id] = engine
 | |
|         }
 | |
|         
 | |
|         return engine
 | |
|     }
 | |
|     
 | |
|     // MARK: - Rewarded Engine Methods
 | |
|     
 | |
|     private func createDefaultRewardedAdEngine(
 | |
|         id: Int,
 | |
|         config: DefaultRewardedConfig
 | |
|     ) -> DefaultRewardedAdEngine? {
 | |
|         if let adSdk = getAdsSdk(adPlatform: AdPlatform.fromName(config.adPlatform))?.obtainRewardedAd(
 | |
|             adConfig: AdConfig(
 | |
|                 engineId: id,
 | |
|                 adUnitId: config.adUnitId,
 | |
|                 adAmazonSlotId: config.adAmazonSlotId
 | |
|             )
 | |
|         ) {
 | |
|            return DefaultRewardedAdEngine(viewController: viewController, id: id, ad: adSdk)
 | |
|         } else {
 | |
|             return nil;
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     private func createMabRewardedEngine(
 | |
|         id: Int,
 | |
|         faUnitId: String,
 | |
|         config: MabRewardedConfig
 | |
|     ) -> MabRewardedEngine {
 | |
|         return MabRewardedEngine(viewController: viewController, id: id, faUnitId: faUnitId, mabConfig: config) {
 | |
|             [weak self] adPlatform, adConfig in
 | |
|             self?.getAdsSdk(adPlatform: adPlatform)?.obtainRewardedAd(adConfig: adConfig)
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     func getRewardedAdEngine(id: Int) -> RewardedAdEngine? {
 | |
|         return rewardedAdEngines[id]
 | |
|     }
 | |
|     
 | |
|     func createRewardedAdEngine(adEngineConfig: AdEngineConfig) -> RewardedAdEngine? {
 | |
|         let id = adEngineConfig.hashCode()
 | |
|         logInfo("createRewardedAdEngine: \(id)")
 | |
|         
 | |
|         let engine = getRewardedAdEngine(id: id) ?? {
 | |
|             switch adEngineConfig.strategy {
 | |
|             case RewardedStrategy.default.rawValue:
 | |
|                 guard let config = try? DefaultRewardedConfig(adEngineConfig.config) else {
 | |
|                     return nil;
 | |
|                 }
 | |
|                 return createDefaultRewardedAdEngine(
 | |
|                     id: id,
 | |
|                     config: config
 | |
|                 )
 | |
|             case RewardedStrategy.mab.rawValue:
 | |
|                 guard let config = try? MabRewardedConfig(adEngineConfig.config) else {
 | |
|                     return nil;
 | |
|                 }
 | |
|                 return createMabRewardedEngine(id: id, faUnitId: adEngineConfig.faUnitId, config: config)
 | |
|                 
 | |
|             default:
 | |
|                 guard let config = try? DefaultRewardedConfig(adEngineConfig.config) else {
 | |
|                     return nil;
 | |
|                 }
 | |
|                 return createDefaultRewardedAdEngine(
 | |
|                     id: id,
 | |
|                     config: config
 | |
|                 )
 | |
|             }
 | |
|         }()
 | |
|         
 | |
|         if let engine = engine {
 | |
|             rewardedAdEngines[id] = engine
 | |
|         }
 | |
|         
 | |
|         return engine
 | |
|     }
 | |
|     
 | |
|     // MARK: - Banner Engine Methods
 | |
|     
 | |
|     private func createDefaultBannerAdEngine(
 | |
|         id: Int,
 | |
|         config: DefaultBannerConfig
 | |
|     ) -> DefaultBannerAdEngine? {
 | |
|         if let adSdk = getAdsSdk(adPlatform: AdPlatform.fromName(config.adPlatform))?.obtainBannerAd(
 | |
|             adConfig: AdConfig(
 | |
|                 engineId: id,
 | |
|                 adUnitId: config.adUnitId,
 | |
|                 adAmazonSlotId: config.adAmazonSlotId
 | |
|             )
 | |
|         ) {
 | |
|            return DefaultBannerAdEngine(viewController: viewController, id: id, ad: adSdk)
 | |
|         } else {
 | |
|             return nil;
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     func getBannerAdEngine(id: Int) -> BannerAdEngine? {
 | |
|         return bannerAdEngines[id]
 | |
|     }
 | |
|     
 | |
|     func createBannerAdEngine(adEngineConfig: AdEngineConfig) -> BannerAdEngine? {
 | |
|         let id = adEngineConfig.hashCode()
 | |
|         logInfo("createBannerAdEngine: \(id)")
 | |
|         
 | |
|         let engine = getBannerAdEngine(id: id) ?? {
 | |
|             switch adEngineConfig.strategy {
 | |
|             case BannerStrategy.default.rawValue:
 | |
|                 guard let config = try? DefaultBannerConfig(adEngineConfig.config) else {
 | |
|                     return nil;
 | |
|                 }
 | |
|                 return createDefaultBannerAdEngine(
 | |
|                     id: id,
 | |
|                     config: config
 | |
|                 )
 | |
|                 
 | |
|             default:
 | |
|                 guard let config = try? DefaultBannerConfig(adEngineConfig.config) else {
 | |
|                     return nil;
 | |
|                 }
 | |
|                 return createDefaultBannerAdEngine(
 | |
|                     id: id,
 | |
|                     config: config
 | |
|                 )
 | |
|             }
 | |
|         }()
 | |
|         
 | |
|         if let engine = engine {
 | |
|             bannerAdEngines[id] = engine
 | |
|         }
 | |
|         
 | |
|         return engine
 | |
|     }
 | |
|     
 | |
|     // MARK: - MRec Engine Methods
 | |
|     
 | |
|     private func createDefaultMRecAdEngine(
 | |
|         id: Int,
 | |
|         config: DefaultMRecConfig
 | |
|     ) -> DefaultMRecAdEngine? {
 | |
|         if let adSdk = getAdsSdk(adPlatform: AdPlatform.fromName(config.adPlatform))?.obtainMRecAd(
 | |
|             adConfig: AdConfig(
 | |
|                 engineId: id,
 | |
|                 adUnitId: config.adUnitId,
 | |
|                 adAmazonSlotId: config.adAmazonSlotId
 | |
|             )
 | |
|         ) {
 | |
|            return DefaultMRecAdEngine(viewController: viewController, id: id, ad: adSdk)
 | |
|         } else {
 | |
|             return nil;
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     func getMRecAdEngine(id: Int) -> MRecAdEngine? {
 | |
|         return mrecAdEngines[id]
 | |
|     }
 | |
|     
 | |
|     func createMRecAdEngine(adEngineConfig: AdEngineConfig) -> MRecAdEngine? {
 | |
|         let id = adEngineConfig.hashCode()
 | |
|         logInfo("createMRecAdEngine: \(id)")
 | |
|         
 | |
|         let engine = getMRecAdEngine(id: id) ?? {
 | |
|             switch adEngineConfig.strategy {
 | |
|             case BannerStrategy.default.rawValue:
 | |
|                 guard let config = try? DefaultMRecConfig(adEngineConfig.config) else {
 | |
|                     return nil;
 | |
|                 }
 | |
|                 return createDefaultMRecAdEngine(
 | |
|                     id: id,
 | |
|                     config: config
 | |
|                 )
 | |
|                 
 | |
|             default:
 | |
|                 guard let config = try? DefaultMRecConfig(adEngineConfig.config) else {
 | |
|                     return nil;
 | |
|                 }
 | |
|                 return createDefaultMRecAdEngine(
 | |
|                     id: id,
 | |
|                     config: config
 | |
|                 )
 | |
|             }
 | |
|         }()
 | |
|         
 | |
|         if let engine = engine {
 | |
|             mrecAdEngines[id] = engine
 | |
|         }
 | |
|         
 | |
|         return engine
 | |
|     }
 | |
|     
 | |
|     func dispatchOrientationUpdate(orientation: ScreenOrientation) {
 | |
|         let body: (Any) throws -> Void = { it in
 | |
|             (it as? OrientationAware)?.onOrientationUpdate(orientation: orientation)
 | |
|         }
 | |
|         try? interstitialAdEngines.values.forEach(body)
 | |
|         try? bannerAdEngines.values.forEach(body)
 | |
|         try? rewardedAdEngines.values.forEach(body)
 | |
|         try? mrecAdEngines.values.forEach(body)
 | |
|     }
 | |
|     
 | |
|     // for testing only!
 | |
|     func clearCachedEngines() {
 | |
|         interstitialAdEngines.removeAll()
 | |
|         bannerAdEngines.removeAll()
 | |
|         rewardedAdEngines.removeAll()
 | |
|         mrecAdEngines.removeAll()
 | |
|     }
 | |
|     
 | |
| }
 | |
| 
 | |
| // MARK: - Hashable Extension for AdEngineConfig
 | |
| 
 | |
| extension AdEngineConfig: Hashable {
 | |
|     func hashCode() -> Int {
 | |
|         return hashValue
 | |
|     }
 | |
|     public static func == (lhs: AdEngineConfig, rhs: AdEngineConfig) -> Bool {
 | |
|         return lhs.strategy == rhs.strategy
 | |
|         && (lhs.config as NSDictionary).isEqual(to: rhs.config)
 | |
|     }
 | |
| 
 | |
| 
 | |
|     public func hash(into hasher: inout Hasher) {
 | |
|         hasher.combine(strategy)
 | |
|         for (key, value) in config {
 | |
|             hasher.combine(key)
 | |
|             if let hashableValue = value as? (any Hashable) {
 | |
|                 hasher.combine(hashableValue)
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| // MARK: - Hashable Extensions
 | |
| 
 | |
| extension Int {
 | |
|     func hashCode() -> Int {
 | |
|         return self
 | |
|     }
 | |
| }
 | |
| 
 | |
| extension String {
 | |
|     func hashCode() -> Int {
 | |
|         var h: Int = 0
 | |
|         for c in self.unicodeScalars {
 | |
|             h = 31 &* h &+ Int(c.value)
 | |
|         }
 | |
|         return h
 | |
|     }
 | |
| }
 |