Commit 61b9882d by Demid Merzlyakov

Merge branch 'develop' into release/5.4.1

# Conflicts:
#	1Weather.xcodeproj/project.pbxproj
parents 0498fb9a 7bbad031
...@@ -28,6 +28,16 @@ ...@@ -28,6 +28,16 @@
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"> shouldUseLaunchSchemeArgsEnv = "YES">
<Testables> <Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "F2D8A742269FFDC60060F36A"
BuildableName = "1WeatherTests.xctest"
BlueprintName = "1WeatherTests"
ReferencedContainer = "container:1Weather.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables> </Testables>
</TestAction> </TestAction>
<LaunchAction <LaunchAction
......
...@@ -80,8 +80,16 @@ public class AdView: UIView { ...@@ -80,8 +80,16 @@ public class AdView: UIView {
guard let placementName = self.placementName else { return nil } guard let placementName = self.placementName else { return nil }
return configManager.adConfig.placement(named: placementName) return configManager.adConfig.placement(named: placementName)
} }
private lazy var terceptManager: TerceptSDKManager = {
return Dependency.shared.getDependency()
}()
private var adTracker : CustomTargetedAdLifeCycleTrackable? {
guard let adUnitID = placement?.adUnitId else { return nil }
return terceptManager.getTracker(with: adUnitID)
}
internal var configManager: AdConfigManager { internal var configManager: AdConfigManager {
return AdConfigManager.shared return AdConfigManager.shared
} }
...@@ -138,8 +146,7 @@ public class AdView: UIView { ...@@ -138,8 +146,7 @@ public class AdView: UIView {
log.warning("failed to guess the top view controller.") log.warning("failed to guess the top view controller.")
return return
} }
bannerView = NativeBannerContainerView(adUnitId: placement.adUnitId, adType: adType, rootViewController: topViewController) bannerView = NativeBannerContainerView(adUnitId: placement.adUnitId, adType: adType, adLifeCycleTracker: adTracker, rootViewController: topViewController)
if let bannerView = bannerView { if let bannerView = bannerView {
bannerView.loggingAlias = logName bannerView.loggingAlias = logName
...@@ -328,6 +335,14 @@ extension AdView { ...@@ -328,6 +335,14 @@ extension AdView {
self.updateA9BidObject(requestAdWhenDone: false) self.updateA9BidObject(requestAdWhenDone: false)
} }
let addTrackerKeys = adTracker?.getCustomTrackableKeys()
if addTrackerKeys?.isEmpty == false {
keywords = keywords ?? [:]
for keyValue in addTrackerKeys ?? [:] {
keywords?[keyValue.key] = keyValue.value
}
}
return keywords return keywords
} }
} }
......
...@@ -14,6 +14,7 @@ import OneWeatherAnalytics ...@@ -14,6 +14,7 @@ import OneWeatherAnalytics
final class NativeAdItem: NSObject { final class NativeAdItem: NSObject {
let log = AdLogger(componentName: "NativeAdItem") let log = AdLogger(componentName: "NativeAdItem")
private var adLifeCycleTracker: AdLifeCycleTrackable?
enum AdType { enum AdType {
case native case native
...@@ -47,16 +48,18 @@ final class NativeAdItem: NSObject { ...@@ -47,16 +48,18 @@ final class NativeAdItem: NSObject {
return nativeAd != nil ? .native : .banner return nativeAd != nil ? .native : .banner
} }
init(nativeAd: GADNativeAd?, adUnitId: String?) { init(nativeAd: GADNativeAd?, adUnitId: String?, adLifeCycleTracker: AdLifeCycleTrackable?) {
super.init() super.init()
self.nativeAd = nativeAd self.nativeAd = nativeAd
self.adLifeCycleTracker = adLifeCycleTracker
self.nativeAd?.delegate = self self.nativeAd?.delegate = self
self.adUnitId = adUnitId self.adUnitId = adUnitId
} }
init(bannerAd: GAMBannerView, adUnitId: String?) { init(bannerAd: GAMBannerView, adUnitId: String?, adLifeCycleTracker: AdLifeCycleTrackable?) {
super.init() super.init()
self.bannerAd = bannerAd self.bannerAd = bannerAd
self.adLifeCycleTracker = adLifeCycleTracker
self.bannerAd?.delegate = self self.bannerAd?.delegate = self
self.adUnitId = adUnitId self.adUnitId = adUnitId
} }
...@@ -79,20 +82,30 @@ extension NativeAdItem: GADNativeAdDelegate { ...@@ -79,20 +82,30 @@ extension NativeAdItem: GADNativeAdDelegate {
params[.ANALYTICS_KEY_AD_ADAPTER] = adNetworkName params[.ANALYTICS_KEY_AD_ADAPTER] = adNetworkName
analytics(log: .ANALYTICS_AD_IMPRESSION, params: params) analytics(log: .ANALYTICS_AD_IMPRESSION, params: params)
adLifeCycleTracker?.recordAdState(.adImpression)
}
func nativeAdDidRecordClick(_ nativeAd: GADNativeAd) {
log.debug("NativeAd did record click")
analytics(log: .ANALYTICS_AD_CLICKED, params: analyticsParams)
adLifeCycleTracker?.recordAdState(.adClicked)
} }
func nativeAdWillPresentScreen(_ nativeAd: GADNativeAd) { func nativeAdWillPresentScreen(_ nativeAd: GADNativeAd) {
log.debug("NativeAd Will present Modal") log.debug("NativeAd Will present Modal")
analytics(log: .ANALYTICS_AD_CLICKED, params: analyticsParams) analytics(log: .ANALYTICS_AD_CLICKED, params: analyticsParams)
adLifeCycleTracker?.recordAdState(.adOpened)
} }
func nativeAdDidDismissScreen(_ nativeAd: GADNativeAd) { func nativeAdDidDismissScreen(_ nativeAd: GADNativeAd) {
log.debug("NativeAd Did Dismiss screen") log.debug("NativeAd Did Dismiss screen")
adLifeCycleTracker?.recordAdState(.adClosed)
} }
func nativeAdWillLeaveApplication(_ nativeAd: GADNativeAd) { func nativeAdWillLeaveApplication(_ nativeAd: GADNativeAd) {
log.info("NativeAd Will Leave Application") log.info("NativeAd Will Leave Application")
analytics(log: .ANALYTICS_AD_CLICKED, params: analyticsParams) analytics(log: .ANALYTICS_AD_CLICKED, params: analyticsParams)
adLifeCycleTracker?.recordAdState(.adLeftApplication)
} }
} }
...@@ -100,15 +113,18 @@ extension NativeAdItem: GADBannerViewDelegate { ...@@ -100,15 +113,18 @@ extension NativeAdItem: GADBannerViewDelegate {
func bannerViewDidRecordImpression(_ bannerView: GADBannerView) { func bannerViewDidRecordImpression(_ bannerView: GADBannerView) {
log.info("Impression recorded (banner)") log.info("Impression recorded (banner)")
analytics(log: .ANALYTICS_AD_IMPRESSION) analytics(log: .ANALYTICS_AD_IMPRESSION)
adLifeCycleTracker?.recordAdState(.adImpression)
} }
func bannerViewWillPresentScreen(_ bannerView: GADBannerView) { func bannerViewWillPresentScreen(_ bannerView: GADBannerView) {
log.info("Click recorded (will present screen)") log.info("Click recorded (will present screen)")
analytics(log: .ANALYTICS_AD_CLICKED) analytics(log: .ANALYTICS_AD_CLICKED)
adLifeCycleTracker?.recordAdState(.adOpened)
} }
func adViewWillLeaveApplication(_ bannerView: GADBannerView) { func adViewWillLeaveApplication(_ bannerView: GADBannerView) {
log.info("Click recorded (will leave application)") log.info("Click recorded (will leave application)")
analytics(log: .ANALYTICS_AD_CLICKED) analytics(log: .ANALYTICS_AD_CLICKED)
adLifeCycleTracker?.recordAdState(.adLeftApplication)
} }
} }
...@@ -24,7 +24,7 @@ class NativeBannerContainerView: UIView { ...@@ -24,7 +24,7 @@ class NativeBannerContainerView: UIView {
private var adLoader: NativeAdLoader private var adLoader: NativeAdLoader
private let adType: AdType private let adType: AdType
private var adLifeCycleTracker: AdLifeCycleTrackable?
weak var delegate: NativeBannerContainerViewDelegate? weak var delegate: NativeBannerContainerViewDelegate?
public var loggingAlias: String? { public var loggingAlias: String? {
...@@ -33,9 +33,13 @@ class NativeBannerContainerView: UIView { ...@@ -33,9 +33,13 @@ class NativeBannerContainerView: UIView {
} }
} }
init(adUnitId: String, adType: AdType, rootViewController: UIViewController) { init(adUnitId: String,
adType: AdType,
adLifeCycleTracker: AdLifeCycleTrackable? = nil,
rootViewController: UIViewController) {
self.adType = adType self.adType = adType
self.adLoader = NativeAdLoader(adUnitId: adUnitId, rootViewController: rootViewController, adTypes: [.native, .gamBanner]) self.adLoader = NativeAdLoader(adUnitId: adUnitId, rootViewController: rootViewController, adTypes: [.native, .gamBanner])
self.adLifeCycleTracker = adLifeCycleTracker
super.init(frame: .zero) super.init(frame: .zero)
self.adLoader.delegate = self self.adLoader.delegate = self
} }
...@@ -81,15 +85,17 @@ extension NativeBannerContainerView: NativeAdLoaderDelegate { ...@@ -81,15 +85,17 @@ extension NativeBannerContainerView: NativeAdLoaderDelegate {
func adLoader(_ adLoader: GADAdLoader, didReceive nativeAd: GADNativeAd) { func adLoader(_ adLoader: GADAdLoader, didReceive nativeAd: GADNativeAd) {
log.debug("Banner ad recieved (native_banner) by: \(String(describing: nativeAd.responseInfo.adNetworkClassName))") log.debug("Banner ad recieved (native_banner) by: \(String(describing: nativeAd.responseInfo.adNetworkClassName))")
guard let adView = NativeAdView.instantiateWithXib(adType: adType) else { return } guard let adView = NativeAdView.instantiateWithXib(adType: adType) else { return }
let nativeAdItem = NativeAdItem(nativeAd: nativeAd, adUnitId: adLoader.adUnitID) let nativeAdItem = NativeAdItem(nativeAd: nativeAd, adUnitId: adLoader.adUnitID, adLifeCycleTracker: adLifeCycleTracker)
adView.nativeAdItem = nativeAdItem adView.nativeAdItem = nativeAdItem
addAsSubview(view: adView) addAsSubview(view: adView)
print("native ad loader: \(String(describing: nativeAd.headline))") print("native ad loader: \(String(describing: nativeAd.headline))")
delegate?.adLoader(adLoader, didReceive: nativeAd) delegate?.adLoader(adLoader, didReceive: nativeAd)
adLifeCycleTracker?.recordAdState(.adLoaded)
} }
func adLoader(_ adLoader: GADAdLoader, didFailToReceiveAdWithError error: Error) { func adLoader(_ adLoader: GADAdLoader, didFailToReceiveAdWithError error: Error) {
delegate?.adLoader(adLoader, didFailToReceiveAdWithError: error) delegate?.adLoader(adLoader, didFailToReceiveAdWithError: error)
adLifeCycleTracker?.recordAdState(.adFailedToLoad)
} }
func adLoader(_ adLoader: GADAdLoader, didReceived bannerView: GAMBannerView) { func adLoader(_ adLoader: GADAdLoader, didReceived bannerView: GAMBannerView) {
...@@ -98,6 +104,7 @@ extension NativeBannerContainerView: NativeAdLoaderDelegate { ...@@ -98,6 +104,7 @@ extension NativeBannerContainerView: NativeAdLoaderDelegate {
addAsSubview(view: bannerView) addAsSubview(view: bannerView)
delegate?.adLoader(adLoader, didReceived: bannerView) delegate?.adLoader(adLoader, didReceived: bannerView)
adLifeCycleTracker?.recordAdState(.adLoaded)
} }
} }
...@@ -106,15 +113,26 @@ extension NativeBannerContainerView: GADBannerViewDelegate { ...@@ -106,15 +113,26 @@ extension NativeBannerContainerView: GADBannerViewDelegate {
func bannerViewDidRecordImpression(_ bannerView: GADBannerView) { func bannerViewDidRecordImpression(_ bannerView: GADBannerView) {
log.info("Impression") log.info("Impression")
analytics(log: .ANALYTICS_AD_IMPRESSION) analytics(log: .ANALYTICS_AD_IMPRESSION)
adLifeCycleTracker?.recordAdState(.adImpression)
} }
func bannerViewWillPresentScreen(_ bannerView: GADBannerView) { func bannerViewWillPresentScreen(_ bannerView: GADBannerView) {
log.info("Click (will present screen)") log.info("Click (will present screen)")
analytics(log: .ANALYTICS_AD_CLICKED) analytics(log: .ANALYTICS_AD_CLICKED)
adLifeCycleTracker?.recordAdState(.adOpened)
} }
func adViewWillLeaveApplication(_ bannerView: GADBannerView) { func adViewWillLeaveApplication(_ bannerView: GADBannerView) {
log.info("Click (will leave application)") log.info("Click (will leave application)")
analytics(log: .ANALYTICS_AD_CLICKED) analytics(log: .ANALYTICS_AD_CLICKED)
adLifeCycleTracker?.recordAdState(.adLeftApplication)
}
func bannerViewDidRecordClick(_ bannerView: GADBannerView) {
adLifeCycleTracker?.recordAdState(.adClicked)
}
func bannerViewWillDismissScreen(_ bannerView: GADBannerView) {
adLifeCycleTracker?.recordAdState(.adClosed)
} }
} }
...@@ -137,6 +137,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate { ...@@ -137,6 +137,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
settings.widgetPromotionTriggerCount = 0 settings.widgetPromotionTriggerCount = 0
} }
} }
// Initializing Essential Dependencies
EssentialDependencies().resolve()
return true return true
} }
...@@ -251,6 +253,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate { ...@@ -251,6 +253,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
availabilityCheckers[feature] = activeProSubscription availabilityCheckers[feature] = activeProSubscription
case .extendedHourlyForecast: case .extendedHourlyForecast:
availabilityCheckers[feature] = activeProSubscription availabilityCheckers[feature] = activeProSubscription
case .terceptSdk:
break // config only
} }
} }
...@@ -355,3 +359,12 @@ extension AppDelegate: SettingsAppDelegate { ...@@ -355,3 +359,12 @@ extension AppDelegate: SettingsAppDelegate {
UIApplication.shared.open(appSettingsURL) UIApplication.shared.open(appSettingsURL)
} }
} }
// This class is placed here so no one else can access its initializer other than AppDelegate, Please remove it from here once we move all to other initializations file
class EssentialDependencies {
fileprivate init() { }
func resolve() {
let _: TerceptSDKManager = Dependency.shared.getDependency()
}
}
//
// AppInfo.swift
// 1Weather
//
// Created by Shailesh on 29/07/21.
//
import UIKit
import AdSupport
struct AppInfo {
static var idfa: String? { ASIdentifierManager.shared().advertisingIdentifier.uuidString
}
static let idfv: String? = UIDevice.current.identifierForVendor?.uuidString
static var appVersion: String = {
let appInfoDict = Bundle.main.infoDictionary
let appVersion: String = (appInfoDict?["CFBundleShortVersionString"] as? String) ?? "Unknown"
let buildNumber: String = (appInfoDict?[kCFBundleVersionKey as String] as? String) ?? ""
return "\(appVersion)(\(buildNumber))"
}()
}
...@@ -31,5 +31,7 @@ ...@@ -31,5 +31,7 @@
&quot;a9_refresh_rate&quot;: 0, &quot;a9_refresh_rate&quot;: 0,
&quot;placements&quot;: {} &quot;placements&quot;: {}
}</string> }</string>
<key>ios_terceptsdk_enabled</key>
<true/>
</dict> </dict>
</plist> </plist>
//
// Dependency.swift
// 1Weather
//
// Created by Shailesh on 14/07/21.
//
import Foundation
/*
Adding the class, to reduce use of single instances
whichever thing that we can use this to provide as and when dependency values and functionalities needed
*/
protocol DependencyRepresentable {
init()
}
class Dependency {
static var shared = Dependency()
private init() { }
private var dependencyMap: [String: DependencyRepresentable] = [:]
func getDependency<T: DependencyRepresentable>() -> T {
guard let dependency: T = dependencyMap[String(describing: T.self)] as? T else {
let dependency = T()
dependencyMap[String(describing: T.self)] = dependency
return dependency
}
return dependency
}
}
...@@ -133,6 +133,8 @@ class CCPAHelper { ...@@ -133,6 +133,8 @@ class CCPAHelper {
FBAdSettings.setAdvertiserTrackingEnabled(canCollectData) FBAdSettings.setAdvertiserTrackingEnabled(canCollectData)
let terceptSDKManager: TerceptSDKManager? = Dependency.shared.getDependency()
terceptSDKManager?.canCollectData = canCollectData
// https://ams.amazon.com/webpublisher/uam/docs/web-integration-documentation/integration-guide/uam-ccpa.html?source=menu // https://ams.amazon.com/webpublisher/uam/docs/web-integration-documentation/integration-guide/uam-ccpa.html?source=menu
if self.canCollectData == nil { if self.canCollectData == nil {
A9Cache.shared.ccpaPrivacyString = "1\(self.shownPrivacyNoticeBefore ? "Y" : "N")-" A9Cache.shared.ccpaPrivacyString = "1\(self.shownPrivacyNoticeBefore ? "Y" : "N")-"
......
...@@ -47,7 +47,8 @@ public class ConfigManager { ...@@ -47,7 +47,8 @@ public class ConfigManager {
.nwsAlertsViaMoEngage: true, .nwsAlertsViaMoEngage: true,
.attPrompt: false, .attPrompt: false,
.shortsLastNudge: false, .shortsLastNudge: false,
.onboarding: false .onboarding: false,
.terceptSdk: false
], subscriptionsConfig: SubscriptionsListConfig() ], subscriptionsConfig: SubscriptionsListConfig()
) )
...@@ -195,6 +196,8 @@ fileprivate extension AppFeature { ...@@ -195,6 +196,8 @@ fileprivate extension AppFeature {
return "shorts_swipe_down_nudge_enabled" return "shorts_swipe_down_nudge_enabled"
case .onboarding: case .onboarding:
return "ios_show_onboarding" return "ios_show_onboarding"
case .terceptSdk:
return "ios_terceptsdk_enabled"
case .ads, .airQualityIndex, .minutelyForecast, .shorts, .subscription, .subscriptionForPro, .extendedDailyForecast, .extendedHourlyForecast: case .ads, .airQualityIndex, .minutelyForecast, .shorts, .subscription, .subscriptionForPro, .extendedDailyForecast, .extendedHourlyForecast:
return nil return nil
// don't use 'default', so that we didn't add new features here in the future. // don't use 'default', so that we didn't add new features here in the future.
......
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
//
// StubTerceptOptimizer.swift
// 1WeatherTests
//
// Created by Shailesh on 15/07/21.
//
import Foundation
@testable import _Weather
class StubTerceptOptimizer: TerceptOptimizer {
private let customTargettingKeys: [String : String?]
private(set) var initParamsMethodParams: (String, String, [String: Any]?)? = nil
private(set) var fetchMethodParams: [String]?
private(set) var setCustomParametersMethodParams: [String: String]?
private(set) var sentEventDataCalled: Bool = false
private(set) var logEventMethodParams: (String?, String?, [String: Any])?
init(customTargettingKeys: [String : String?]) {
self.customTargettingKeys = customTargettingKeys
}
func initParams(_ IDFA: String, _ IDFV: String, _ params: [String : Any]?) {
self.initParamsMethodParams = (IDFA, IDFV, params)
}
func fetch(_ adunits: [String]?) {
self.fetchMethodParams = adunits
}
func setCustomParameters(_ params: [String : String]) {
self.setCustomParametersMethodParams = params
}
func sendEventsData() {
self.sentEventDataCalled = true
}
func getCustomTargetingKeys(_ adunit: String?) -> [String : String?] {
return customTargettingKeys
}
func logEvent(_ adunit: String?, _ event: String?, _ customParams: [String : Any]) -> Bool {
self.logEventMethodParams = (adunit, event, customParams)
return true
}
}
extension AdLifeCycleState: CaseIterable {
public static var allCases: [AdLifeCycleState] = [.adClicked, .adClosed, .adFailedToLoad, .adImpression, .adLeftApplication, .adLoaded, .adOpened]
}
//
// TerceptSDKEnablerTests.swift
// 1WeatherTests
//
// Created by Shailesh on 02/08/21.
//
import XCTest
@testable import _Weather
class TerceptSDKEnablerTests: XCTestCase {
private var isInitCalled = false
private var isDeinitCalled = false
private var enabler = TerceptSDKEnabler()
override func setUp() {
super.setUp()
enabler = TerceptSDKEnabler()
self.enabler.attachObserver(observer: TerceptConditionsObserver(initSDK: {
self.isInitCalled = true
}, deinitSDK: {
self.isDeinitCalled = true
}))
}
override func tearDown() {
super.tearDown()
isInitCalled = false
isDeinitCalled = false
}
func testEnablingCondition() {
enabler.enableDataCollection(true)
XCTAssertFalse(isInitCalled)
XCTAssertFalse(isDeinitCalled)
enabler.setConfigToggle(true)
XCTAssertTrue(isInitCalled)
XCTAssertFalse(isDeinitCalled)
}
func testDelayedEnabledCondition() {
enabler.enableDataCollection(false)
XCTAssertFalse(isInitCalled)
XCTAssertFalse(isDeinitCalled)
enabler.setConfigToggle(false)
XCTAssertFalse(isInitCalled)
XCTAssertFalse(isDeinitCalled)
enabler.enableDataCollection(true)
XCTAssertFalse(isInitCalled)
XCTAssertFalse(isDeinitCalled)
enabler.setConfigToggle(true)
XCTAssertTrue(isInitCalled)
XCTAssertFalse(isDeinitCalled)
}
func testDataCollectionDeniedCondition() {
enabler.enableDataCollection(true)
XCTAssertFalse(isInitCalled)
XCTAssertFalse(isDeinitCalled)
enabler.setConfigToggle(true)
XCTAssertTrue(isInitCalled)
XCTAssertFalse(isDeinitCalled)
// Resetting init
isInitCalled = false
enabler.enableDataCollection(false)
XCTAssertFalse(isInitCalled)
XCTAssertTrue(isDeinitCalled)
}
func testRuntimeConfigOffCondition() {
enabler.enableDataCollection(true)
XCTAssertFalse(isInitCalled)
XCTAssertFalse(isDeinitCalled)
enabler.setConfigToggle(true)
XCTAssertTrue(isInitCalled)
XCTAssertFalse(isDeinitCalled)
// Resetting init
isInitCalled = false
enabler.setConfigToggle(false)
XCTAssertFalse(isInitCalled)
XCTAssertTrue(isDeinitCalled)
}
func testMultipleDeinitCallingIssue() {
testDataCollectionDeniedCondition()
isDeinitCalled = false
enabler.enableDataCollection(false)
XCTAssertFalse(isInitCalled)
XCTAssertFalse(isDeinitCalled)
}
func testMultipleConfigEnableCalls() {
enabler.enableDataCollection(true)
enabler.setConfigToggle(true)
isInitCalled = false
enabler.setConfigToggle(true)
XCTAssertFalse(isInitCalled)
XCTAssertFalse(isDeinitCalled)
enabler.setConfigToggle(false)
XCTAssertFalse(isInitCalled)
XCTAssertTrue(isDeinitCalled)
}
func testMultipleDataCollectionCalls() {
enabler.enableDataCollection(true)
enabler.setConfigToggle(true)
isInitCalled = false
enabler.enableDataCollection(true)
XCTAssertFalse(isInitCalled)
XCTAssertFalse(isDeinitCalled)
enabler.enableDataCollection(false)
XCTAssertFalse(isInitCalled)
XCTAssertTrue(isDeinitCalled)
}
}
//
// TerceptSDKEnabler.swift
// 1Weather
//
// Created by Shailesh on 02/08/21.
//
//TODO: got to get rid of all of this...
struct TerceptConditionsObserver {
let initSDK: (() -> Void)
let deinitSDK: (() -> Void)
}
final class TerceptSDKEnabler {
private var observer: TerceptConditionsObserver?
private var configToggle: Bool?
private var canCollectData: Bool?
private var hasInitializedSDK: Bool = false
private func invokeObserver() {
guard let firebaseConfig = configToggle,
let canCollectData = canCollectData else { return }
if firebaseConfig, canCollectData {
if !hasInitializedSDK {
hasInitializedSDK = true
observer?.initSDK()
}
} else if hasInitializedSDK {
hasInitializedSDK = false
observer?.deinitSDK()
}
}
func attachObserver(observer: TerceptConditionsObserver) {
self.observer = observer
}
func setConfigToggle(_ configToggle: Bool) {
self.configToggle = configToggle
invokeObserver()
}
func enableDataCollection(_ canCollectData: Bool) {
self.canCollectData = canCollectData
invokeObserver()
}
}
//
// TerceptSDKManager.swift
// 1Weather
//
// Created by Shailesh on 13/07/21.
//
import UIKit
import TerceptSDK
import AlgoliaSearchClient
import OneWeatherAnalytics
protocol TerceptOptimizer: AdEventLoggable {
func fetch(_ adunits: [String]?)
func setCustomParameters(_ params: [String : String])
func sendEventsData()
func getCustomTargetingKeys(_ adunit: String?) -> [String : String?]
func initParams(_ IDFA: String, _ IDFV: String, _ params: [String : Any]?)
}
struct TerceptOptimizerWrapper: TerceptOptimizer {
private let wrapperOptimizer: TerceptSDK.TerceptOptimization
private let log = Logger(componentName: "Tercept")
public init(optimizer: TerceptSDK.TerceptOptimization) {
wrapperOptimizer = optimizer
}
func fetch(_ adunits: [String]?) {
log.info("fetch for ad units: \(adunits ?? [String]())")
wrapperOptimizer.fetch(adunits)
}
func setCustomParameters(_ params: [String : String]) {
log.info("set custom params: \(params)")
wrapperOptimizer.setCustomParameters(params)
}
func sendEventsData() {
log.info("send events data")
wrapperOptimizer.sendEventsData()
}
func getCustomTargetingKeys(_ adunit: String?) -> [String : String?] {
let result = wrapperOptimizer.getCustomTargetingKeys(adunit)
log.info("custom targeting keys for ad unit: \(adunit ?? "-"): \(result)")
return result
}
func initParams(_ IDFA: String, _ IDFV: String, _ params: [String : Any]?) {
log.info("Initialize with IDFA \(IDFA) IDFV \(IDFV) params: \(params ?? [String: Any]())")
wrapperOptimizer.initParams(IDFA, IDFV, params)
}
func logEvent(_ adunit: String?, _ event: String?, _ customParams: [String : Any]) -> Bool {
let result = wrapperOptimizer.logEvent(adunit, event, customParams)
log.info("log event \(event ?? "-") for ad ad unit: \(adunit ?? "-"); result: \(result)")
return result
}
}
protocol AdEventLoggable {
@discardableResult func logEvent(_ adunit: String?, _ event: String?, _ customParams: [String : Any]) -> Bool
}
final class TerceptSDKManager: AdEventLoggable, DependencyRepresentable {
private var optimizer: TerceptOptimizer?
private let enabler: TerceptSDKEnabler
private let log = Logger(componentName: "Tercept")
private struct Constants {
static let DFPCode: String = "120348554"
static var IDFA: String { AppInfo.idfa ?? "UNKNOWN" }
static var IDFV: String { AppInfo.idfv ?? "UNKNOWN" }
static var version: String { AppInfo.appVersion }
}
var canCollectData: Bool = false {
didSet {
enabler.enableDataCollection(canCollectData)
}
}
required init() {
self.enabler = TerceptSDKEnabler()
attachObserver()
registerNotifications()
}
init(optimizer: TerceptOptimizer, adUnitIDs: [String]) {
self.optimizer = optimizer
self.enabler = TerceptSDKEnabler()
attachObserver()
updateKeys()
optimizer.fetch(adUnitIDs)
registerNotifications()
fetchIfAvailable()
}
//MARK:- Private
private func attachObserver() {
//TODO: got to get rid of all of this...
self.enabler.attachObserver(observer: TerceptConditionsObserver(initSDK: initializeSDK, deinitSDK: deinitSDK))
}
private func initializeSDK() {
log.info("Initialize the SDK")
optimizer = TerceptOptimizerWrapper(optimizer: TerceptOptimization(Constants.DFPCode))
updateKeys()
fetchIfAvailable()
}
private func deinitSDK() {
log.info("Shut down the SDK")
optimizer = nil
}
private func updateKeys() {
let idfa = Constants.IDFA
let idfv = Constants.IDFV
let params = ["appVersion": Constants.version]
log.info("Update keys: IDFA \(idfa) IDFV \(idfv)")
optimizer?.initParams(idfa, idfv, params)
}
private func registerNotifications() {
NotificationCenter.default.addObserver(self,
selector: #selector(handleSwitchToBackground),
name: UIApplication.didEnterBackgroundNotification,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(fetchIfAvailable),
name: .adConfigChanged,
object: nil)
ConfigManager.shared.add(delegate: self)
}
@objc private func fetchIfAvailable() {
guard let placements = ConfigManager.shared.config.adConfig.placements,
!placements.isEmpty else { return }
register(adUnitIDs: placements.values.map { $0.adUnitId })
}
private func register(adUnitIDs: [String]) {
optimizer?.fetch(adUnitIDs)
}
@objc private func handleSwitchToBackground() {
optimizer?.sendEventsData()
}
//MARK:- Public
func getTracker(with adUnitId: String) -> TerceptAdTracker {
return TerceptAdTracker(adUnitId: adUnitId,
logger: self,
customKeys: optimizer?.getCustomTargetingKeys(adUnitId) ?? [:])
}
func setCustomParameters(_ params: [String : String]) {
optimizer?.setCustomParameters(params)
}
@discardableResult func logEvent(_ adunit: String?, _ event: String?, _ customParams: [String : Any]) -> Bool {
return optimizer?.logEvent(adunit, event, customParams) ?? false
}
}
extension TerceptSDKManager: ConfigManagerDelegate {
func dataUpdated(by configManager: ConfigManager) {
enabler.setConfigToggle(configManager.config.isEnabled(feature: .terceptSdk))
}
}
enum AdLifeCycleState: String {
case adClicked = "onAdClicked"
case adClosed = "onAdClosed"
case adFailedToLoad = "onAdFailedToLoad"
case adImpression = "onAdImpression"
case adLeftApplication = "onAdLeftApplication"
case adLoaded = "onAdLoaded"
case adOpened = "onAdOpened"
}
protocol CustomTargetProvidable {
func getCustomTrackableKeys() -> [String: String?]
}
protocol AdLifeCycleTrackable {
func recordAdState(_ state: AdLifeCycleState)
}
typealias CustomTargetedAdLifeCycleTrackable = CustomTargetProvidable & AdLifeCycleTrackable
/// Get instance of TerceptAdTracker from TerceptSDKManager, using func getTracker(with adUnitId: String) method.
final class TerceptAdTracker: CustomTargetedAdLifeCycleTrackable {
private let adUnitId: String
private let customKeys: [String: String?]
private let logger: AdEventLoggable
fileprivate init(adUnitId: String, logger: AdEventLoggable, customKeys: [String: String?]) {
self.adUnitId = adUnitId
self.customKeys = customKeys
self.logger = logger
}
func getCustomTrackableKeys() -> [String: String?] {
return customKeys
}
func recordAdState(_ state: AdLifeCycleState) {
// TODO: unravel all this.
// This will eventually be forwarded to the TerceptOptimizer above, thata will log the info into the console.
logger.logEvent(adUnitId, state.rawValue, [:])
}
}
// Copyright (c) 2021, Tercept (https://www.tercept.com/)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef PublicHeader_h
#define PublicHeader_h
#import <TerceptSDK/TerceptSDK.h>
#import <TerceptSDK/TerceptSDK-Bridging-Header.h>
#endif /* PublicHeader_h */
// Copyright (c) 2021, Tercept (https://www.tercept.com/)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#import <Foundation/Foundation.h>
//! Project version number for TerceptSDK.
FOUNDATION_EXPORT double TerceptSDKVersionNumber;
//! Project version string for TerceptSDK.
FOUNDATION_EXPORT const unsigned char TerceptSDKVersionString[];
// In this header, you should import all the public headers of your framework using statements like
// #import <TerceptSDK/PublicHeader.h>
// swift-interface-format-version: 1.0
// swift-compiler-version: Apple Swift version 5.4 (swiftlang-1205.0.26.9 clang-1205.0.19.55)
// swift-module-flags: -target armv7-apple-ios9.0 -enable-objc-interop -enable-library-evolution -swift-version 5 -enforce-exclusivity=checked -O -module-name TerceptSDK
import Foundation
import SafariServices
import Swift
import UIKit
import WebKit
public protocol Callable {
associatedtype R
func call() -> Self.R
}
public protocol TaskRunner_Callback {
associatedtype R
func onComplete(result: Self.R)
}
@objc public class TerceptOptimization : ObjectiveC.NSObject {
public static let sdkVersion: Swift.String
public static var isDebugMode: Swift.Bool
public init(_ networkCode: Swift.String)
public func initParams(_ IDFA: Swift.String, _ IDFV: Swift.String, _ params: [Swift.String : Any]?)
public func initParams(_ IDFA: Swift.String, _ IDFV: Swift.String)
public func fetch(_ adunits: [Swift.String]?)
public func logEvent(_ adunit: Swift.String?, _ event: Swift.String?) -> Swift.Bool
public func logEvent(_ adunit: Swift.String?, _ event: Swift.String?, _ customParams: [Swift.String : Any]) -> Swift.Bool
public func getEventsData() -> [Swift.String : Any]?
public func sendEventsData()
public func setCustomParameters(_ params: [Swift.String : Swift.String])
public func getCustomTargetingKeys(_ adunit: Swift.String?) -> Swift.Dictionary<Swift.String, Swift.String?>
@objc override dynamic public init()
@objc deinit
}
extension UIDevice {
public static let modelName: Swift.String
}
// swift-interface-format-version: 1.0
// swift-compiler-version: Apple Swift version 5.4 (swiftlang-1205.0.26.9 clang-1205.0.19.55)
// swift-module-flags: -target arm64-apple-ios9.0 -enable-objc-interop -enable-library-evolution -swift-version 5 -enforce-exclusivity=checked -O -module-name TerceptSDK
import Foundation
import SafariServices
import Swift
import UIKit
import WebKit
public protocol Callable {
associatedtype R
func call() -> Self.R
}
public protocol TaskRunner_Callback {
associatedtype R
func onComplete(result: Self.R)
}
@objc public class TerceptOptimization : ObjectiveC.NSObject {
public static let sdkVersion: Swift.String
public static var isDebugMode: Swift.Bool
public init(_ networkCode: Swift.String)
public func initParams(_ IDFA: Swift.String, _ IDFV: Swift.String, _ params: [Swift.String : Any]?)
public func initParams(_ IDFA: Swift.String, _ IDFV: Swift.String)
public func fetch(_ adunits: [Swift.String]?)
public func logEvent(_ adunit: Swift.String?, _ event: Swift.String?) -> Swift.Bool
public func logEvent(_ adunit: Swift.String?, _ event: Swift.String?, _ customParams: [Swift.String : Any]) -> Swift.Bool
public func getEventsData() -> [Swift.String : Any]?
public func sendEventsData()
public func setCustomParameters(_ params: [Swift.String : Swift.String])
public func getCustomTargetingKeys(_ adunit: Swift.String?) -> Swift.Dictionary<Swift.String, Swift.String?>
@objc override dynamic public init()
@objc deinit
}
extension UIDevice {
public static let modelName: Swift.String
}
// swift-interface-format-version: 1.0
// swift-compiler-version: Apple Swift version 5.4 (swiftlang-1205.0.26.9 clang-1205.0.19.55)
// swift-module-flags: -target arm64-apple-ios9.0 -enable-objc-interop -enable-library-evolution -swift-version 5 -enforce-exclusivity=checked -O -module-name TerceptSDK
import Foundation
import SafariServices
import Swift
import UIKit
import WebKit
public protocol Callable {
associatedtype R
func call() -> Self.R
}
public protocol TaskRunner_Callback {
associatedtype R
func onComplete(result: Self.R)
}
@objc public class TerceptOptimization : ObjectiveC.NSObject {
public static let sdkVersion: Swift.String
public static var isDebugMode: Swift.Bool
public init(_ networkCode: Swift.String)
public func initParams(_ IDFA: Swift.String, _ IDFV: Swift.String, _ params: [Swift.String : Any]?)
public func initParams(_ IDFA: Swift.String, _ IDFV: Swift.String)
public func fetch(_ adunits: [Swift.String]?)
public func logEvent(_ adunit: Swift.String?, _ event: Swift.String?) -> Swift.Bool
public func logEvent(_ adunit: Swift.String?, _ event: Swift.String?, _ customParams: [Swift.String : Any]) -> Swift.Bool
public func getEventsData() -> [Swift.String : Any]?
public func sendEventsData()
public func setCustomParameters(_ params: [Swift.String : Swift.String])
public func getCustomTargetingKeys(_ adunit: Swift.String?) -> Swift.Dictionary<Swift.String, Swift.String?>
@objc override dynamic public init()
@objc deinit
}
extension UIDevice {
public static let modelName: Swift.String
}
// swift-interface-format-version: 1.0
// swift-compiler-version: Apple Swift version 5.4 (swiftlang-1205.0.26.9 clang-1205.0.19.55)
// swift-module-flags: -target armv7-apple-ios9.0 -enable-objc-interop -enable-library-evolution -swift-version 5 -enforce-exclusivity=checked -O -module-name TerceptSDK
import Foundation
import SafariServices
import Swift
import UIKit
import WebKit
public protocol Callable {
associatedtype R
func call() -> Self.R
}
public protocol TaskRunner_Callback {
associatedtype R
func onComplete(result: Self.R)
}
@objc public class TerceptOptimization : ObjectiveC.NSObject {
public static let sdkVersion: Swift.String
public static var isDebugMode: Swift.Bool
public init(_ networkCode: Swift.String)
public func initParams(_ IDFA: Swift.String, _ IDFV: Swift.String, _ params: [Swift.String : Any]?)
public func initParams(_ IDFA: Swift.String, _ IDFV: Swift.String)
public func fetch(_ adunits: [Swift.String]?)
public func logEvent(_ adunit: Swift.String?, _ event: Swift.String?) -> Swift.Bool
public func logEvent(_ adunit: Swift.String?, _ event: Swift.String?, _ customParams: [Swift.String : Any]) -> Swift.Bool
public func getEventsData() -> [Swift.String : Any]?
public func sendEventsData()
public func setCustomParameters(_ params: [Swift.String : Swift.String])
public func getCustomTargetingKeys(_ adunit: Swift.String?) -> Swift.Dictionary<Swift.String, Swift.String?>
@objc override dynamic public init()
@objc deinit
}
extension UIDevice {
public static let modelName: Swift.String
}
// swift-interface-format-version: 1.0
// swift-compiler-version: Apple Swift version 5.4 (swiftlang-1205.0.26.9 clang-1205.0.19.55)
// swift-module-flags: -target armv7-apple-ios9.0 -enable-objc-interop -enable-library-evolution -swift-version 5 -enforce-exclusivity=checked -O -module-name TerceptSDK
import Foundation
import SafariServices
import Swift
import UIKit
import WebKit
public protocol Callable {
associatedtype R
func call() -> Self.R
}
public protocol TaskRunner_Callback {
associatedtype R
func onComplete(result: Self.R)
}
@objc public class TerceptOptimization : ObjectiveC.NSObject {
public static let sdkVersion: Swift.String
public static var isDebugMode: Swift.Bool
public init(_ networkCode: Swift.String)
public func initParams(_ IDFA: Swift.String, _ IDFV: Swift.String, _ params: [Swift.String : Any]?)
public func initParams(_ IDFA: Swift.String, _ IDFV: Swift.String)
public func fetch(_ adunits: [Swift.String]?)
public func logEvent(_ adunit: Swift.String?, _ event: Swift.String?) -> Swift.Bool
public func logEvent(_ adunit: Swift.String?, _ event: Swift.String?, _ customParams: [Swift.String : Any]) -> Swift.Bool
public func getEventsData() -> [Swift.String : Any]?
public func sendEventsData()
public func setCustomParameters(_ params: [Swift.String : Swift.String])
public func getCustomTargetingKeys(_ adunit: Swift.String?) -> Swift.Dictionary<Swift.String, Swift.String?>
@objc override dynamic public init()
@objc deinit
}
extension UIDevice {
public static let modelName: Swift.String
}
// swift-interface-format-version: 1.0
// swift-compiler-version: Apple Swift version 5.4 (swiftlang-1205.0.26.9 clang-1205.0.19.55)
// swift-module-flags: -target i386-apple-ios9.0-simulator -enable-objc-interop -enable-library-evolution -swift-version 5 -enforce-exclusivity=checked -O -module-name TerceptSDK
import Foundation
import SafariServices
import Swift
import UIKit
import WebKit
public protocol Callable {
associatedtype R
func call() -> Self.R
}
public protocol TaskRunner_Callback {
associatedtype R
func onComplete(result: Self.R)
}
@objc public class TerceptOptimization : ObjectiveC.NSObject {
public static let sdkVersion: Swift.String
public static var isDebugMode: Swift.Bool
public init(_ networkCode: Swift.String)
public func initParams(_ IDFA: Swift.String, _ IDFV: Swift.String, _ params: [Swift.String : Any]?)
public func initParams(_ IDFA: Swift.String, _ IDFV: Swift.String)
public func fetch(_ adunits: [Swift.String]?)
public func logEvent(_ adunit: Swift.String?, _ event: Swift.String?) -> Swift.Bool
public func logEvent(_ adunit: Swift.String?, _ event: Swift.String?, _ customParams: [Swift.String : Any]) -> Swift.Bool
public func getEventsData() -> [Swift.String : Any]?
public func sendEventsData()
public func setCustomParameters(_ params: [Swift.String : Swift.String])
public func getCustomTargetingKeys(_ adunit: Swift.String?) -> Swift.Dictionary<Swift.String, Swift.String?>
@objc override dynamic public init()
@objc deinit
}
extension UIDevice {
public static let modelName: Swift.String
}
// swift-interface-format-version: 1.0
// swift-compiler-version: Apple Swift version 5.4 (swiftlang-1205.0.26.9 clang-1205.0.19.55)
// swift-module-flags: -target i386-apple-ios9.0-simulator -enable-objc-interop -enable-library-evolution -swift-version 5 -enforce-exclusivity=checked -O -module-name TerceptSDK
import Foundation
import SafariServices
import Swift
import UIKit
import WebKit
public protocol Callable {
associatedtype R
func call() -> Self.R
}
public protocol TaskRunner_Callback {
associatedtype R
func onComplete(result: Self.R)
}
@objc public class TerceptOptimization : ObjectiveC.NSObject {
public static let sdkVersion: Swift.String
public static var isDebugMode: Swift.Bool
public init(_ networkCode: Swift.String)
public func initParams(_ IDFA: Swift.String, _ IDFV: Swift.String, _ params: [Swift.String : Any]?)
public func initParams(_ IDFA: Swift.String, _ IDFV: Swift.String)
public func fetch(_ adunits: [Swift.String]?)
public func logEvent(_ adunit: Swift.String?, _ event: Swift.String?) -> Swift.Bool
public func logEvent(_ adunit: Swift.String?, _ event: Swift.String?, _ customParams: [Swift.String : Any]) -> Swift.Bool
public func getEventsData() -> [Swift.String : Any]?
public func sendEventsData()
public func setCustomParameters(_ params: [Swift.String : Swift.String])
public func getCustomTargetingKeys(_ adunit: Swift.String?) -> Swift.Dictionary<Swift.String, Swift.String?>
@objc override dynamic public init()
@objc deinit
}
extension UIDevice {
public static let modelName: Swift.String
}
// swift-interface-format-version: 1.0
// swift-compiler-version: Apple Swift version 5.4 (swiftlang-1205.0.26.9 clang-1205.0.19.55)
// swift-module-flags: -target x86_64-apple-ios9.0-simulator -enable-objc-interop -enable-library-evolution -swift-version 5 -enforce-exclusivity=checked -O -module-name TerceptSDK
import Foundation
import SafariServices
import Swift
import UIKit
import WebKit
public protocol Callable {
associatedtype R
func call() -> Self.R
}
public protocol TaskRunner_Callback {
associatedtype R
func onComplete(result: Self.R)
}
@objc public class TerceptOptimization : ObjectiveC.NSObject {
public static let sdkVersion: Swift.String
public static var isDebugMode: Swift.Bool
public init(_ networkCode: Swift.String)
public func initParams(_ IDFA: Swift.String, _ IDFV: Swift.String, _ params: [Swift.String : Any]?)
public func initParams(_ IDFA: Swift.String, _ IDFV: Swift.String)
public func fetch(_ adunits: [Swift.String]?)
public func logEvent(_ adunit: Swift.String?, _ event: Swift.String?) -> Swift.Bool
public func logEvent(_ adunit: Swift.String?, _ event: Swift.String?, _ customParams: [Swift.String : Any]) -> Swift.Bool
public func getEventsData() -> [Swift.String : Any]?
public func sendEventsData()
public func setCustomParameters(_ params: [Swift.String : Swift.String])
public func getCustomTargetingKeys(_ adunit: Swift.String?) -> Swift.Dictionary<Swift.String, Swift.String?>
@objc override dynamic public init()
@objc deinit
}
extension UIDevice {
public static let modelName: Swift.String
}
// swift-interface-format-version: 1.0
// swift-compiler-version: Apple Swift version 5.4 (swiftlang-1205.0.26.9 clang-1205.0.19.55)
// swift-module-flags: -target x86_64-apple-ios9.0-simulator -enable-objc-interop -enable-library-evolution -swift-version 5 -enforce-exclusivity=checked -O -module-name TerceptSDK
import Foundation
import SafariServices
import Swift
import UIKit
import WebKit
public protocol Callable {
associatedtype R
func call() -> Self.R
}
public protocol TaskRunner_Callback {
associatedtype R
func onComplete(result: Self.R)
}
@objc public class TerceptOptimization : ObjectiveC.NSObject {
public static let sdkVersion: Swift.String
public static var isDebugMode: Swift.Bool
public init(_ networkCode: Swift.String)
public func initParams(_ IDFA: Swift.String, _ IDFV: Swift.String, _ params: [Swift.String : Any]?)
public func initParams(_ IDFA: Swift.String, _ IDFV: Swift.String)
public func fetch(_ adunits: [Swift.String]?)
public func logEvent(_ adunit: Swift.String?, _ event: Swift.String?) -> Swift.Bool
public func logEvent(_ adunit: Swift.String?, _ event: Swift.String?, _ customParams: [Swift.String : Any]) -> Swift.Bool
public func getEventsData() -> [Swift.String : Any]?
public func sendEventsData()
public func setCustomParameters(_ params: [Swift.String : Swift.String])
public func getCustomTargetingKeys(_ adunit: Swift.String?) -> Swift.Dictionary<Swift.String, Swift.String?>
@objc override dynamic public init()
@objc deinit
}
extension UIDevice {
public static let modelName: Swift.String
}
...@@ -22,4 +22,5 @@ public enum AppFeature: String, Codable, CaseIterable { ...@@ -22,4 +22,5 @@ public enum AppFeature: String, Codable, CaseIterable {
case subscription case subscription
/// Discounted subscription for people who previously purchased an in-app to remove ads /// Discounted subscription for people who previously purchased an in-app to remove ads
case subscriptionForPro case subscriptionForPro
case terceptSdk
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment