FusionAds-iOS/FusionAds/Classes/fusion/engine/AdsEngineManager.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
}
}