Commit c264d4b4 by Dmitriy Stepanets

Merge branch 'develop' into modules

# Conflicts:
#	1Weather.xcodeproj/project.pbxproj
#	1Weather/Analytics/AppAnalytics.swift
#	1Weather/AppDelegate.swift
#	1Weather/Coordinators/DeeplinksRouter.swift
#	1Weather/InApps/OLInAppStoreManager.swift
#	1Weather/Network/PushNotificationsManager.swift
#	Podfile.lock
#	Pods/Manifest.lock
#	Pods/Pods.xcodeproj/project.pbxproj
parents 91c38947 1f1e9901
......@@ -179,6 +179,7 @@
CE13B97C2626FB11007CBD4D /* PSMLocationSDK.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = CE13B7DC262478E7007CBD4D /* PSMLocationSDK.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
CE14445F2638B6CF008E2162 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE14445E2638B6CF008E2162 /* StoreKit.framework */; };
CE376C98261EE484000B1159 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CE376C97261EE484000B1159 /* LaunchScreen.storyboard */; };
CE3C1DB6265536360031BD72 /* AppsFlyerAnalyticsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE3C1DB5265536360031BD72 /* AppsFlyerAnalyticsService.swift */; };
CE578FE525FB415F00E8B85D /* CityCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE578FE225FB415F00E8B85D /* CityCell.swift */; };
CE578FE625FB415F00E8B85D /* LocationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE578FE325FB415F00E8B85D /* LocationViewController.swift */; };
CE578FE725FB415F00E8B85D /* LocationsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE578FE425FB415F00E8B85D /* LocationsViewModel.swift */; };
......@@ -427,6 +428,7 @@
CE14445D2638B6A8008E2162 /* 1Weather.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = 1Weather.entitlements; sourceTree = "<group>"; };
CE14445E2638B6CF008E2162 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };
CE376C97261EE484000B1159 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = "<group>"; };
CE3C1DB5265536360031BD72 /* AppsFlyerAnalyticsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppsFlyerAnalyticsService.swift; sourceTree = "<group>"; };
CE578FE225FB415F00E8B85D /* CityCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CityCell.swift; sourceTree = "<group>"; };
CE578FE325FB415F00E8B85D /* LocationViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocationViewController.swift; sourceTree = "<group>"; };
CE578FE425FB415F00E8B85D /* LocationsViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocationsViewModel.swift; sourceTree = "<group>"; };
......@@ -1231,6 +1233,7 @@
CEF959642600C2F900975FAA /* AnalyticsService.swift */,
CEF959732600C3A400975FAA /* FlurryAnalyticsService.swift */,
CEF9598F2600C5A800975FAA /* MoEngageAnalyticsService.swift */,
CE3C1DB5265536360031BD72 /* AppsFlyerAnalyticsService.swift */,
);
path = Services;
sourceTree = "<group>";
......@@ -1615,6 +1618,7 @@
CD39F2F525DE9571009FE398 /* ArrowButton.swift in Sources */,
CD37D3FE260DF726002669D6 /* SettingsCellFactory.swift in Sources */,
CD8E041625F8F91B001785B6 /* ForecastCellFactory.swift in Sources */,
CE3C1DB6265536360031BD72 /* AppsFlyerAnalyticsService.swift in Sources */,
CDC6125325E79C8F00188DA7 /* DayTimeView.swift in Sources */,
CE13B81B262480B3007CBD4D /* AdView.swift in Sources */,
CD251EDC26036E5400ED7A65 /* DayTimePrecipitationView.swift in Sources */,
......@@ -1674,6 +1678,7 @@
CE13B819262480B3007CBD4D /* A9Cache.swift in Sources */,
CE578FE625FB415F00E8B85D /* LocationViewController.swift in Sources */,
CD86246525E66E8A0097F3FB /* PrecipitationCell.swift in Sources */,
CD80917B2578E4A8003541A4 /* UIViewController+Alert.swift in Sources */,
CEF959932600C63500975FAA /* AppAnalytics.swift in Sources */,
CEE0A1A426317A8F0044C257 /* NWSAlertInfoParser.swift in Sources */,
CEBAC1C62638236D00A89681 /* PushNotificationsManager.swift in Sources */,
......@@ -1875,7 +1880,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 5.0.1;
MARKETING_VERSION = 5.0.2;
PRODUCT_BUNDLE_IDENTIFIER = com.onelouder.oneweather;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
......@@ -1906,7 +1911,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 5.0.1;
MARKETING_VERSION = 5.0.2;
PRODUCT_BUNDLE_IDENTIFIER = com.onelouder.oneweather;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
......@@ -1928,7 +1933,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 5.0.1;
MARKETING_VERSION = 5.0.2;
PRODUCT_BUNDLE_IDENTIFIER = com.onelouder.oneweather.OneWeatherNotificationServiceExtension;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
......@@ -1951,7 +1956,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 5.0.1;
MARKETING_VERSION = 5.0.2;
PRODUCT_BUNDLE_IDENTIFIER = com.onelouder.oneweather.OneWeatherNotificationServiceExtension;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
......
......@@ -12,7 +12,7 @@
<key>OneWeatherNotificationServiceExtension.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>55</integer>
<integer>53</integer>
</dict>
<key>PG (Playground) 1.xcscheme</key>
<dict>
......
......@@ -4,6 +4,10 @@
<dict>
<key>aps-environment</key>
<string>development</string>
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:1weather.onelink.me</string>
</array>
<key>com.apple.security.application-groups</key>
<array>
<string>group.com.onelouder.oneweather.MoEngage</string>
......
......@@ -7,6 +7,10 @@
import Foundation
/// See
/// https://inmobi.sharepoint.com/:x:/r/sites/blend-all/_layouts/15/guestaccess.aspx?e=KujQS1&share=EROF-1U3ZkVCstR4vAIN8kgB2emhefIzh5yZnZ4v02oIyQ
/// for reference
public enum AnalyticsEvent: String {
//TODO: rename to Swifty names. This is a legacy from the old app.
case ANALYTICS_LAUNCH_FROM_WIDGET = "LAUNCH FROM WIDGET" // params: type
......@@ -85,4 +89,11 @@ public enum AnalyticsEvent: String {
case ANALYTICS_A9_BID_RECEIVED = "A9_BID_RECEIVED"
case ANALYTICS_AD_CLICKED = "AD_CLICKED"
case ANALYTICS_APP_OPEN = "APP_OPEN"
/// FTUE Funnel: User has saved his first city after installing the app.
case ANALYTICS_USER_QUALIFIED = "USER_QUALIFIED"
/// FTUE Funnel: User comes back to the app between the 3rd day after being qualified and 6th day.
case ANALYTICS_D3_RETAINED = "D3_RETAINED"
/// FTUE Funnel: When the user opens the app for the first time
case ANALYTICS_FIRST_OPEN = "FIRST_OPEN"
}
......@@ -16,7 +16,7 @@ public class AppAnalytics {
self.services = services
}
public static let shared = AppAnalytics(services: [FlurryAnalyticsService(), MoEngageAnalyticsService()])
public static let shared = AppAnalytics(services: [FlurryAnalyticsService(), MoEngageAnalyticsService(), AppsFlyerAnalyticsService()])
public func log(event: AnalyticsEvent, params: [AnalyticsParameter: Any]? = nil) {
var loggedTo = [String]()
......
......@@ -12,3 +12,16 @@ public protocol AnalyticsService {
var eventsWhitelist: Set<AnalyticsEvent>? { get }
func log(event: AnalyticsEvent, params: [AnalyticsParameter: Any]?)
}
extension AnalyticsService {
func stringKeyedParams(from params: [AnalyticsParameter: Any]?) -> [String: Any]? {
guard let params = params else {
return nil
}
var stringKeyedParams = [String: Any]()
for (key, value) in params {
stringKeyedParams[key.rawValue] = value
}
return stringKeyedParams
}
}
//
// AppsFlyerAnalyticsService.swift
// 1Weather
//
// Created by Demid Merzlyakov on 19.05.2021.
//
import Foundation
import AppsFlyerLib
internal struct AppsFlyerAnalyticsService: AnalyticsService {
public let name: String = "AppsFlyer"
let eventsWhitelist: Set<AnalyticsEvent>? = [.ANALYTICS_APP_OPEN, .ANALYTICS_USER_QUALIFIED, .ANALYTICS_D3_RETAINED, .ANALYTICS_FIRST_OPEN]
func log(event: AnalyticsEvent, params: [AnalyticsParameter : Any]?) {
AppsFlyerLib.shared().logEvent(event.rawValue, withValues: stringKeyedParams(from: params))
}
}
......@@ -13,15 +13,6 @@ internal struct FlurryAnalyticsService: AnalyticsService {
let eventsWhitelist: Set<AnalyticsEvent>? = nil
func log(event: AnalyticsEvent, params: [AnalyticsParameter : Any]?) {
// Not sure we need this conversion
var stringKeyedParams: [String: Any]? = nil
if let params = params {
stringKeyedParams = [String: Any]()
for (key, value) in params {
stringKeyedParams?[key.rawValue] = value
}
}
Flurry.logEvent(event.rawValue, withParameters: stringKeyedParams)
Flurry.logEvent(event.rawValue, withParameters: stringKeyedParams(from: params))
}
}
......@@ -13,13 +13,7 @@ internal struct MoEngageAnalyticsService: AnalyticsService {
let eventsWhitelist: Set<AnalyticsEvent>? = nil
func log(event: AnalyticsEvent, params: [AnalyticsParameter : Any]?) {
var stringKeyedParams: [String: Any]? = nil
if let params = params {
stringKeyedParams = [String: Any]()
for (key, value) in params {
stringKeyedParams?[key.rawValue] = value
}
}
let stringKeyedParams = stringKeyedParams(from: params)
if let params = stringKeyedParams {
if let nsParams = (params as NSDictionary).mutableCopy() as? NSMutableDictionary { // should never fail
......
......@@ -14,12 +14,16 @@ import GoogleMobileAds
import Swarm
import DTBiOSSDK
import OneWeatherCore
import AppsFlyerLib
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
private let appsFlyer = AppsFlyerLib.shared()
private let appsFlyerLog = Logger(componentName: "AppsFlyer")
private let log = Logger(componentName: "AppDelegate")
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
ThemeManager.refreshAppearance()
......@@ -31,13 +35,36 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
self.window = UIWindow(frame: UIScreen.main.bounds)
appsFlyerLog.info("AppsFlyer initialize with AppsFlyerId: \(kAppsFlyerId), Apple App ID: \(kAppsFlyerAppId)")
appsFlyer.appsFlyerDevKey = kAppsFlyerId
appsFlyer.appleAppID = kAppsFlyerAppId
appsFlyer.delegate = self
appsFlyer.deepLinkDelegate = self
#if DEBUG
appsFlyer.isDebug = true
#else
appsFlyer.isDebug = false
#endif
// Note that the Amazon SDK will get assigned a proper value for consent status inside CCPAHelper.onAppLaunch
// So, make sure this call happens after the
CCPAHelper.shared.onAppLaunch()
if CCPAHelper.shared.isNewUser && Settings.shared.firstOpenDate == nil {
analytics(log: .ANALYTICS_FIRST_OPEN)
Settings.shared.firstOpenDate = Date()
}
if let userQualifiedDate = Settings.shared.userQualifiedDate {
let timeSinceQualified = Date().timeIntervalSince(userQualifiedDate)
let day = TimeInterval(3600 * 24)
if timeSinceQualified >= 3 * day && timeSinceQualified < 6 * day {
analytics(log: .ANALYTICS_D3_RETAINED)
}
}
// As of DTB 3.4.6 the Amazon SDK freezes the main thread on startup for a couple of seconds, which got us rejected during an AppStore Review. We're going to move this initialization to the AppDelegate for now. The consent status is going to be set earlier within CCPAHelper.shared.onAppLaunch(), so make sure CCPAHelper's onAppLaunch is called before Amazon's setAppKey
// TODO: remove setAppKey from here, if Amazon has fixed the freeze on startup.
Logger(componentName: "Amazon A9").info("Amazon SDK initialization start")
log.info("Amazon SDK (Amazon A9) initialization start")
DTBAds.sharedInstance().setAppKey(a9AppKey)
FirebaseApp.configure()
ConfigManager.shared.updateConfig()
......@@ -55,7 +82,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
flurrySession = flurrySession?.withDataSaleOptOut(!canCollectData)
}
Logger(componentName: "Flurry").info("Initialize Flurry.")
log.info("Initialize Flurry with partner ID: \(kFlurryPartnerId)")
Flurry.startSession(kFlurryPartnerId, with: FlurrySessionBuilder
.init()
.withCrashReporting(false)
......@@ -65,13 +92,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
var moEngageConfig = MOSDKConfig(appID: kMoEngageAppId)
moEngageConfig.appGroupID = "group.com.onelouder.oneweather.MoEngage"
let moeLogger = Logger(componentName: "MoEngage")
#if DEBUG
moeLogger.info("Initialize MoEngage (TEST)")
log.info("Initialize MoEngage (TEST)")
MoEngage.enableSDKLogs(true)
MoEngage.sharedInstance().initializeTest(with: moEngageConfig, andLaunchOptions: launchOptions)
#else
moeLogger.info("Initialize MoEngage (LIVE)")
log.info("Initialize MoEngage (LIVE)")
MoEngage.sharedInstance().initializeLive(with: moEngageConfig, andLaunchOptions: launchOptions)
#endif
......@@ -79,8 +105,30 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
return true
}
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
log.info("Open URL: \(url) with options: \(options)")
let oneWeatherRouter = DeeplinksRouter()
oneWeatherRouter.open(url: url)
return true
}
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
log.info("Continue userActivity \(userActivity)")
appsFlyer.continue(userActivity, restorationHandler: nil)
return true
}
func applicationDidBecomeActive(_ application: UIApplication) {
LocationManager.shared.updateEverythingIfNeeded()
appsFlyer.start { [weak self] dictionary, error in
if let error = error {
self?.appsFlyerLog.error("AppsFlyer start error: \(error)")
}
else {
self?.appsFlyerLog.info("AppsFlyer start result: \(dictionary)")
}
}
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
......@@ -88,3 +136,63 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
}
}
extension AppDelegate: AppsFlyerLibDelegate {
func onConversionDataSuccess(_ conversionInfo: [AnyHashable : Any]) {
let status = conversionInfo["af_status"] as? String
if status == "Non-organic" {
let sourceID = conversionInfo["media_source"] as? String
let campaign = conversionInfo["campaign"] as? String
appsFlyerLog.info("This is a non-organic install. Media source: \(sourceID ?? String(describing: conversionInfo["media_source"])) Campaign: \(campaign ?? String(describing: conversionInfo["campaign"]))")
}
else if status == "Organic" {
appsFlyerLog.info("This is an organic install.")
}
}
func onConversionDataFail(_ error: Error) {
appsFlyerLog.error("conversion data fail: \(error)")
}
func onAppOpenAttribution(_ attributionData: [AnyHashable : Any]) {
appsFlyerLog.info("app open attribution: \(attributionData)")
}
func onAppOpenAttributionFailure(_ error: Error) {
appsFlyerLog.error("app open attribution error: \(error)")
}
}
extension AppDelegate: DeepLinkDelegate {
func didResolveDeepLink(_ result: DeepLinkResult) {
switch result.status {
case .notFound:
appsFlyerLog.info("Deeplink: not found")
return
case .failure:
if let error = result.error {
appsFlyerLog.error("Deeplink: error: \(error)")
}
else {
appsFlyerLog.error("Deeplink: error (unknown)")
}
return
case .found:
appsFlyerLog.info("Deeplink: found!")
}
guard let deepLinkObj:DeepLink = result.deepLink else {
appsFlyerLog.error("Deeplink: Could not extract deep link object")
return
}
log.debug("Deeplink: it's a \(deepLinkObj.isDeferred ? "deferred" : "direct") deeplink.")
guard let deeplink = deepLinkObj.deeplinkValue else {
appsFlyerLog.error("Deeplink: Could not extract deep_link_value from deep link object")
return
}
guard let url = URL(string: deeplink) else {
appsFlyerLog.error("Deeplink: Couldn't create a URL from deeplink: \(deeplink)")
return
}
let router = DeeplinksRouter()
router.open(url: url)
}
}
......@@ -17,6 +17,10 @@ let kOLAppMetricsKey: String = "OLAppMetricsKey"
let WDT_APP_ID = "e3b73414"
let WDT_APP_KEY = "25e8d6b72de3bcd528f7769b073cc335"
//MARK: - keys for AppsFlyer
let kAppsFlyerId = "62r3MKqdd6eqtj5jN5wdm6"
let kAppsFlyerAppId = "1044809694" // taken from the app page in AppStoreConnect
//MARK: - InApp
let kInAppOneWeatherProId = "com.onelouder.oneweather.inapp1"
......
......@@ -45,13 +45,8 @@ class AppCoordinator: Coordinator {
tabBarController.setupTabBar()
if Settings.shared.locationDidAdded {
window.rootViewController = tabBarController
}
else {
let animationController = SplashAnimationViewController(appCoordinator: self)
window.rootViewController = animationController
}
let animationController = SplashAnimationViewController(appCoordinator: self)
window.rootViewController = animationController
self.window.makeKeyAndVisible()
}
......
......@@ -6,6 +6,8 @@
// Copyright © 2021 OneLouder, Inc. All rights reserved.
//
import UIKit
import AppsFlyerLib
import Foundation
import OneWeatherCore
......@@ -81,13 +83,17 @@ class DeeplinksRouter {
return result
}
public func open(url: URL) {
public func open(url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) {
guard self.is1WUrl(url) else {
log.info("not 1Weather URL, ignore: \(url)")
log.info("not 1Weather URL, trying AppsFlyer: \(url)")
AppsFlyerLib.shared().handleOpen(url, options: options)
return
}
log.info("open URL: \(url)")
log.info("open 1Weather URL: \(url)")
var pathComponents = url.pathComponents
if let host = url.host {
pathComponents.insert(host, at: 0)
}
while let currentComponent = pathComponents.popLast() {
if let parsedComponent = UrlPathComponent(rawValue: currentComponent.lowercased()) {
log.debug("Parsed path: \(parsedComponent.rawValue)")
......
......@@ -8,6 +8,7 @@
import UIKit
import StoreKit
import AppsFlyerLib
import OneWeatherCore
// Ported from ObjC
......@@ -40,6 +41,7 @@ class OLInAppStoreManager: NSObject {
}
var currentRequest: SKProductsRequest?
var currentProduct: SKProduct?
// MARK: - public methods
func attemptPurchase(forProductId productId: String) {
......@@ -89,6 +91,7 @@ extension OLInAppStoreManager: SKProductsRequestDelegate {
}
}
if let validProduct = validProduct {
currentProduct = validProduct
let payment = SKPayment(product: validProduct)
delegate?.inAppStoreManager(self, purchaseWillBeAdded: payment)
SKPaymentQueue.default().add(self)
......@@ -110,13 +113,43 @@ extension OLInAppStoreManager: SKPaymentTransactionObserver {
switch transaction.transactionState {
case .purchased:
delegate?.inAppStoreManager(self, purchaseCompletedForProductId: transaction.payment.productIdentifier)
if let currentProduct = self.currentProduct,
currentProduct.productIdentifier == transaction.payment.productIdentifier
{
if let currencyCode = currentProduct.priceLocale.currencyCode {
#if DEBUG
AppsFlyerLib.shared().useReceiptValidationSandbox = true
#endif
AppsFlyerLib.shared().validateAndLog(inAppPurchase: currentProduct.productIdentifier,
price: currentProduct.price.stringValue,
currency: currencyCode,
transactionId: transaction.transactionIdentifier,
additionalParameters: nil,
success: { [weak self] in
guard let dictionary = $0 as? [String: Any] else {
self?.log.info("AppsFlyer verified purchase.")
return
}
self?.log.info("AppsFlyer verified purchase: \(dictionary)")
},
failure: { [weak self] error, result in
self?.log.error("AppsFlyer purchase verification failed: error: \(String(describing: error)), result: \(String(describing: result))")
})
}
else {
log.error("AppsFlyer purchase event: currency not found.")
}
}
else {
log.error("AppsFlyer purchase event: could find matching product.")
}
SKPaymentQueue.default().finishTransaction(transaction)
case .failed:
if let error = transaction.error {
log.error("SKPaymentTransactionStateFailedError: \(error)")
log.error("Transaction failed: \(error)")
}
else {
log.error("SKPaymentTransactionStateFailedError: unknown error")
log.error("Transaction failed: unknown error")
}
delegate?.inAppStoreManager(self, purchaseFailedFor: transaction)
SKPaymentQueue.default().finishTransaction(transaction)
......@@ -156,7 +189,6 @@ extension OLInAppStoreManager: SKPaymentTransactionObserver {
// MARK: - SKRequestDelegate
extension OLInAppStoreManager: SKRequestDelegate {
func requestDidFinish(_ request: SKRequest) {
log.debug("requestDidFinish")
}
......
......@@ -13,6 +13,7 @@ import IASDKCore
import MoEngage
import Flurry_iOS_SDK
import Firebase
import FirebaseCoreDiagnostics
import CommonCrypto
import CryptoKit
import FBAudienceNetwork
......@@ -149,9 +150,8 @@ class CCPAHelper {
}
// Firebase
Firebase.Analytics.setUserProperty(canCollectData ? "true" : "false", forName: AnalyticsUserPropertyAllowAdPersonalizationSignals)
Firebase.Analytics.setAnalyticsCollectionEnabled(canCollectData)
Analytics.setUserProperty(canCollectData ? "true" : "false", forName: AnalyticsUserPropertyAllowAdPersonalizationSignals)
Analytics.setAnalyticsCollectionEnabled(canCollectData)
PSMLocation.sharedInstance().halted = !canCollectData
......
......@@ -125,7 +125,7 @@ public class LocationManager {
return _selectedLocationIndex
}
set {
if !Settings.shared.locationDidAdded {
if !Settings.shared.locationDidAdded && newValue != nil {
Settings.shared.locationDidAdded = true
}
_selectedLocationIndex = newValue
......@@ -274,7 +274,6 @@ public class LocationManager {
guard let legacyLocations = legacyLocations else {
storageLoadingCompletion(locations, selectedIndex, error)
fatalError("Should never happen. Either legacyLocations or migrationError must be not nil")
return
}
for location: PartialLocation in legacyLocations {
......@@ -302,7 +301,6 @@ public class LocationManager {
log.info("Update all: update default location if needed.")
updateWeather(for: defaultLocation, updateType: .full)
updateHealth(for: defaultLocation)
updateNotifications(for: defaultLocation)
return
}
log.info("Update all \(locations.count) locations if needed...")
......@@ -481,6 +479,10 @@ public class LocationManager {
}
}
else {
if locations.count == 0 && Settings.shared.userQualifiedDate == nil {
analytics(log: .ANALYTICS_USER_QUALIFIED)
Settings.shared.userQualifiedDate = Date()
}
locations = [location] + locations
analytics(log: .ANALYTICS_ADD_LOCATION)
}
......@@ -494,6 +496,10 @@ public class LocationManager {
}
}
else {
if locations.count == 0 && Settings.shared.userQualifiedDate == nil {
analytics(log: .ANALYTICS_USER_QUALIFIED)
Settings.shared.userQualifiedDate = Date()
}
locations.append(location)
analytics(log: .ANALYTICS_ADD_LOCATION)
if selectLocation {
......
......@@ -8,6 +8,7 @@
import Foundation
import MoEngage
import AppsFlyerLib
import OneWeatherCore
public class PushNotificationsManager: NSObject {
......@@ -88,6 +89,7 @@ public class PushNotificationsManager: NSObject {
self.lastKnownPushToken = tokenString
log.info("Got new APNS token: \(tokenString)")
MoEngage.sharedInstance().setPushToken(pushToken)
AppsFlyerLib.shared().registerUninstall(pushToken)
}
}
......@@ -143,6 +145,15 @@ extension PushNotificationsManager: UNUserNotificationCenterDelegate {
log.info("MoEngage push: location found: \(newLoc)")
}
private func isMoEngagePush(_ response: UNNotificationResponse) -> Bool {
let userInfo = response.notification.request.content.userInfo
guard userInfo["moengage"] as? [String: Any] != nil else {
log.debug("No MoEngage data found.")
return false
}
return true
}
private func handleMoEngageDeeplinks(for response: UNNotificationResponse) {
let userInfo = response.notification.request.content.userInfo
......@@ -203,8 +214,16 @@ extension PushNotificationsManager: UNUserNotificationCenterDelegate {
}
public func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
MoEngage.sharedInstance().userNotificationCenter(center, didReceive: response) // not sure we should call it for PushPin notifications, too
handleMoEngageDeeplinks(for: response)
MoEngage.sharedInstance().userNotificationCenter(center, didReceive: response) // not sure we should call it for AppsFlyer notifications
log.debug("Got a push notification: \(response.notification.request.content.userInfo)")
if isMoEngagePush(response) {
handleMoEngageDeeplinks(for: response)
}
else {
log.info("Handle push notification with AppsFlyer")
AppsFlyerLib.shared().handlePushNotification(response.notification.request.content.userInfo)
}
completionHandler()
}
......
{
"images" : [
{
"filename" : "splash_background.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true,
"template-rendering-intent" : "original"
}
}
......@@ -6,12 +6,6 @@
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<customFonts key="customFonts">
<array key="SF-Pro.ttf">
<string>SFPro-Bold</string>
<string>SFPro-Regular</string>
</array>
</customFonts>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
......@@ -25,42 +19,16 @@
<rect key="frame" x="0.0" y="0.0" width="390" height="844"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="pgM-ha-uFh" userLabel="Logo Container View">
<rect key="frame" x="103.66666666666667" y="386" width="182.66666666666663" height="72"/>
<subviews>
<imageView clipsSubviews="YES" clearsContextBeforeDrawing="NO" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="launch_app_icon" translatesAutoresizingMaskIntoConstraints="NO" id="vyA-OC-sOG" userLabel="Logo Image View">
<rect key="frame" x="8" y="0.0" width="48" height="48"/>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Proud to serve 50 million users" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mIG-va-ePB">
<rect key="frame" x="4" y="58" width="175" height="14"/>
<fontDescription key="fontDescription" name="SFPro-Regular" family="SF Pro" pointSize="12"/>
<color key="textColor" red="0.99999600649999998" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="1Weather" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cpE-Vg-eMU">
<rect key="frame" x="67.999999999999972" y="10" width="106.66666666666666" height="28"/>
<fontDescription key="fontDescription" name="SFPro-Bold" family="SF Pro" pointSize="24"/>
<color key="textColor" red="0.99999600649999998" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" red="0.070963539179999993" green="0.098073191939999999" blue="0.1129643098" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
<constraints>
<constraint firstItem="vyA-OC-sOG" firstAttribute="leading" secondItem="pgM-ha-uFh" secondAttribute="leading" constant="8" id="0lS-xt-LeQ"/>
<constraint firstItem="mIG-va-ePB" firstAttribute="centerX" secondItem="pgM-ha-uFh" secondAttribute="centerX" id="8NR-gd-Gar"/>
<constraint firstItem="mIG-va-ePB" firstAttribute="top" secondItem="vyA-OC-sOG" secondAttribute="bottom" constant="10" id="DYb-sz-DkP"/>
<constraint firstItem="vyA-OC-sOG" firstAttribute="top" secondItem="pgM-ha-uFh" secondAttribute="top" id="XGC-8j-hAa"/>
<constraint firstItem="cpE-Vg-eMU" firstAttribute="leading" secondItem="vyA-OC-sOG" secondAttribute="trailing" constant="12" id="cfL-yp-Lz8"/>
<constraint firstItem="cpE-Vg-eMU" firstAttribute="centerY" secondItem="vyA-OC-sOG" secondAttribute="centerY" id="eT7-JO-S3T"/>
<constraint firstAttribute="bottom" secondItem="mIG-va-ePB" secondAttribute="bottom" id="nuo-0R-06a"/>
<constraint firstAttribute="trailing" secondItem="cpE-Vg-eMU" secondAttribute="trailing" constant="8" id="p9F-o6-J4N"/>
</constraints>
</view>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="splash_background" translatesAutoresizingMaskIntoConstraints="NO" id="yBk-JY-Vpa">
<rect key="frame" x="0.0" y="0.0" width="390" height="844"/>
</imageView>
</subviews>
<color key="backgroundColor" red="0.074509803921568626" green="0.098039215686274508" blue="0.11372549019607843" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
<constraints>
<constraint firstItem="pgM-ha-uFh" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="lC5-Ud-bhG"/>
<constraint firstItem="pgM-ha-uFh" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="tis-hw-QqQ"/>
<constraint firstAttribute="bottom" secondItem="yBk-JY-Vpa" secondAttribute="bottom" id="Pj0-xJ-24h"/>
<constraint firstItem="yBk-JY-Vpa" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="dqM-6Q-E0L"/>
<constraint firstAttribute="trailing" secondItem="yBk-JY-Vpa" secondAttribute="trailing" id="nVI-bi-CTI"/>
<constraint firstItem="yBk-JY-Vpa" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" id="x99-B0-qB3"/>
</constraints>
</view>
</viewController>
......@@ -70,6 +38,6 @@
</scene>
</scenes>
<resources>
<image name="launch_app_icon" width="48" height="48"/>
<image name="splash_background" width="390" height="788"/>
</resources>
</document>
......@@ -7,9 +7,11 @@
import UIKit
import Lottie
import OneWeatherCore
class SplashAnimationViewController: UIViewController {
private let appCoordinator:AppCoordinator
private let backgroundImageView = UIImageView()
private let animation = Animation.named("splash")
private var animationView:AnimationView?
private let playButton = UIButton()
......@@ -26,7 +28,17 @@ class SplashAnimationViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor(hex: 0x13191D)
view.backgroundColor = .black
//Background image
backgroundImageView.image = UIImage(named: "splash_background")
backgroundImageView.contentMode = .scaleAspectFill
view.addSubview(backgroundImageView)
backgroundImageView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
//Animation
animationView = AnimationView(animation: animation)
view.addSubview(animationView!)
......@@ -37,10 +49,32 @@ class SplashAnimationViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if Settings.shared.locationDidAdded {
cityAnimation()
}
else {
noCityAnimation()
}
}
private func noCityAnimation() {
self.animationView?.play(completion: {[weak self] _ in
DispatchQueue.global().asyncAfter(deadline: .now() + 0.5) {
self?.appCoordinator.finishAnimation()
}
})
}
private func cityAnimation() {
self.animationView?.alpha = 0
self.animationView?.currentProgress = 1
UIView.animate(withDuration: 0.5) {
self.animationView?.alpha = 1
} completion: { _ in
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
self.appCoordinator.finishAnimation()
}
}
}
}
......@@ -36,7 +36,11 @@ public final class Logger {
guard level.rawValue >= minLogLevel.rawValue else {
return
}
Crashlytics.crashlytics().log(message)
onMain {
Crashlytics.crashlytics().log(message)
}
let prefix = "\(Logger.prefix) \(componentName) [\(logLevelString(level: level))]"
if message.count < maxCharsPerMessage {
NSLog("\(prefix): \(message)")
......
......@@ -83,6 +83,12 @@ public class Settings {
@UserDefaultsBasicValue(key: "selectedLayer")
public var selectedLayerId:String = DefaultSettingsFactory().getSettings().selectedLayerId
@UserDefaultsOptionalValue("userQualifiedDate")
public var userQualifiedDate: Date?
@UserDefaultsOptionalValue("firstOpenDate")
public var firstOpenDate: Date?
@UserDefaultsBasicValue(key: "locationDidAdded")
public var locationDidAdded:Bool = false
......
......@@ -28,6 +28,7 @@ target '1Weather' do
pod 'AlgoliaSearchClient', '~> 8.2'
pod 'Flurry-iOS-SDK/FlurrySDK'
pod 'MoEngage-iOS-SDK'
pod 'AppsFlyerFramework'
# Recommended: Add the Firebase pod for Google Analytics
pod 'Firebase/Analytics'
......
......@@ -2,6 +2,9 @@ PODS:
- AlgoliaSearchClient (8.8.1):
- Logging
- AmazonPublisherServicesSDK (4.0.0)
- AppsFlyerFramework (6.3.0):
- AppsFlyerFramework/Main (= 6.3.0)
- AppsFlyerFramework/Main (6.3.0)
- BezierKit (0.11.0)
- Cirque (1.0.3)
- FBAudienceNetwork (6.4.1):
......@@ -181,6 +184,7 @@ PODS:
DEPENDENCIES:
- AlgoliaSearchClient (~> 8.2)
- AmazonPublisherServicesSDK
- AppsFlyerFramework
- BezierKit
- Cirque (from `https://github.com/StepanetsDmtry/Cirque.git`)
- Firebase/Analytics
......@@ -205,6 +209,7 @@ SPEC REPOS:
trunk:
- AlgoliaSearchClient
- AmazonPublisherServicesSDK
- AppsFlyerFramework
- BezierKit
- FBAudienceNetwork
- FBSDKCoreKit
......@@ -256,6 +261,7 @@ CHECKOUT OPTIONS:
SPEC CHECKSUMS:
AlgoliaSearchClient: bbafe7f014cc0b474646d794ae3675ef4e92f0d5
AmazonPublisherServicesSDK: f73e281872525d1b929dca506c3a0332d4f902fa
AppsFlyerFramework: e5b13250a1b68887213efcd854238791d17cf50b
BezierKit: 8b9bc3aaaa34ede809ff7c7c8aecc2bbe3b86a89
Cirque: 1eb134f2180b33107106dc72e47340aefb054da3
FBAudienceNetwork: 1974ec59ef88102f284c29941d73d0cbec3f2874
......@@ -291,6 +297,6 @@ SPEC CHECKSUMS:
Swarm: 95393cd52715744c94e3a8475bc20b4de5d79f35
XMLCoder: f884dfa894a6f8b7dce465e4f6c02963bf17e028
PODFILE CHECKSUM: adfe38105edb3c330317f791b2bf0a4481f8137c
PODFILE CHECKSUM: 091a3e21eac8770cf37838fb2380f320d1c7b921
COCOAPODS: 1.10.1
<?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>AvailableLibraries</key>
<array>
<dict>
<key>LibraryIdentifier</key>
<string>macos-arm64_x86_64</string>
<key>LibraryPath</key>
<string>AppsFlyerLib.framework</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
<string>x86_64</string>
</array>
<key>SupportedPlatform</key>
<string>macos</string>
</dict>
<dict>
<key>LibraryIdentifier</key>
<string>tvos-arm64</string>
<key>LibraryPath</key>
<string>AppsFlyerLib.framework</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
</array>
<key>SupportedPlatform</key>
<string>tvos</string>
</dict>
<dict>
<key>LibraryIdentifier</key>
<string>ios-arm64_x86_64-maccatalyst</string>
<key>LibraryPath</key>
<string>AppsFlyerLib.framework</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
<string>x86_64</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
<key>SupportedPlatformVariant</key>
<string>maccatalyst</string>
</dict>
<dict>
<key>LibraryIdentifier</key>
<string>ios-arm64_i386_x86_64-simulator</string>
<key>LibraryPath</key>
<string>AppsFlyerLib.framework</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
<string>i386</string>
<string>x86_64</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict>
<dict>
<key>LibraryIdentifier</key>
<string>tvos-arm64_x86_64-simulator</string>
<key>LibraryPath</key>
<string>AppsFlyerLib.framework</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
<string>x86_64</string>
</array>
<key>SupportedPlatform</key>
<string>tvos</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict>
<dict>
<key>LibraryIdentifier</key>
<string>ios-arm64_armv7</string>
<key>LibraryPath</key>
<string>AppsFlyerLib.framework</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
<string>armv7</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
</dict>
</array>
<key>CFBundlePackageType</key>
<string>XFWK</string>
<key>XCFrameworkFormatVersion</key>
<string>1.0</string>
</dict>
</plist>
//
// CrossPromotionHelper.h
// AppsFlyerLib
//
// Created by Gil Meroz on 27/01/2017.
//
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/**
AppsFlyer allows you to log and attribute installs originating
from cross promotion campaigns of your existing apps.
Afterwards, you can optimize on your cross-promotion traffic to get even better results.
*/
@interface AppsFlyerCrossPromotionHelper : NSObject
/**
To log an impression use the following API call.
Make sure to use the promoted App ID as it appears within the AppsFlyer dashboard.
@param appID Promoted App ID
@param campaign A campaign name
@param parameters Additional params like `@{@"af_sub1": @"val", @"custom_param": @"val2" }`
*/
+ (void)logCrossPromoteImpression:(nonnull NSString *)appID
campaign:(nullable NSString *)campaign
parameters:(nullable NSDictionary *)parameters;
/**
iOS allows you to utilize the StoreKit component to open
the App Store while remaining in the context of your app.
More details at https://support.appsflyer.com/hc/en-us/articles/115004481946-Cross-Promotion-Tracking#tracking-cross-promotion-impressions
@param appID Promoted App ID
@param campaign A campaign name
@param parameters Additional params like `@{@"af_sub1": @"val", @"custom_param": @"val2" }`
@param openStoreBlock Contains promoted `clickURL`
*/
+ (void)logAndOpenStore:(nonnull NSString *)appID
campaign:(nullable NSString *)campaign
parameters:(nullable NSDictionary *)parameters
openStore:(void (^)(NSURLSession *urlSession, NSURL *clickURL))openStoreBlock;
@end
NS_ASSUME_NONNULL_END
//
// AFSDKDeeplink.h
// AppsFlyerLib
//
// Created by Andrii Hahan on 20.08.2020.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
NS_SWIFT_NAME(DeepLink)
@interface AppsFlyerDeepLink : NSObject
- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)new NS_UNAVAILABLE;
@property (readonly, nonnull) NSDictionary<NSString *, id> *clickEvent;
@property (readonly, nullable) NSString *deeplinkValue;
@property (readonly, nullable) NSString *matchType;
@property (readonly, nullable) NSString *clickHTTPReferrer;
@property (readonly, nullable) NSString *mediaSource;
@property (readonly, nullable) NSString *campaign;
@property (readonly, nullable) NSString *campaignId;
@property (readonly, nullable) NSString *afSub1;
@property (readonly, nullable) NSString *afSub2;
@property (readonly, nullable) NSString *afSub3;
@property (readonly, nullable) NSString *afSub4;
@property (readonly, nullable) NSString *afSub5;
@property (readonly) BOOL isDeferred;
- (NSString *)toString;
@end
NS_ASSUME_NONNULL_END
//
// AFSDKDeeplinkResult.h
// AppsFlyerLib
//
// Created by Andrii Hahan on 20.08.2020.
//
#import <Foundation/Foundation.h>
@class AppsFlyerDeepLink;
typedef NS_CLOSED_ENUM(NSUInteger, AFSDKDeepLinkResultStatus) {
AFSDKDeepLinkResultStatusNotFound,
AFSDKDeepLinkResultStatusFound,
AFSDKDeepLinkResultStatusFailure,
} NS_SWIFT_NAME(DeepLinkResultStatus);
NS_SWIFT_NAME(DeepLinkResult)
@interface AppsFlyerDeepLinkResult : NSObject
- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)new NS_UNAVAILABLE;
@property(readonly) AFSDKDeepLinkResultStatus status;
@property(readonly, nullable) AppsFlyerDeepLink *deepLink;
@property(readonly, nullable) NSError *error;
@end
//
// LinkGenerator.h
// AppsFlyerLib
//
// Created by Gil Meroz on 27/01/2017.
//
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/**
Payload container for the `generateInviteUrlWithLinkGenerator:completionHandler:` from `AppsFlyerShareInviteHelper`
*/
@interface AppsFlyerLinkGenerator : NSObject
/// Instance initialization is not allowed. Use generated instance
/// from `-[AppsFlyerShareInviteHelper generateInviteUrlWithLinkGenerator:completionHandler]`
- (instancetype)init NS_UNAVAILABLE;
/// Instance initialization is not allowed. Use generated instance
/// from `-[AppsFlyerShareInviteHelper generateInviteUrlWithLinkGenerator:completionHandler]`
+ (instancetype)new NS_UNAVAILABLE;
@property(nonatomic, nullable) NSString *brandDomain;
/// The channel through which the invite was sent (e.g. Facebook/Gmail/etc.). Usage: Recommended
- (void)setChannel :(nonnull NSString *)channel;
/// ReferrerCustomerId setter
- (void)setReferrerCustomerId:(nonnull NSString *)referrerCustomerId;
/// A campaign name. Usage: Optional
- (void)setCampaign :(nonnull NSString *)campaign;
/// ReferrerUID setter
- (void)setReferrerUID :(nonnull NSString *)referrerUID;
/// Referrer name
- (void)setReferrerName :(nonnull NSString *)referrerName;
/// The URL to referrer user avatar. Usage: Optional
- (void)setReferrerImageURL :(nonnull NSString *)referrerImageURL;
/// AppleAppID
- (void)setAppleAppID :(nonnull NSString *)appleAppID;
/// Deeplink path
- (void)setDeeplinkPath :(nonnull NSString *)deeplinkPath;
/// Base deeplink path
- (void)setBaseDeeplink :(nonnull NSString *)baseDeeplink;
/// A single key value custom parameter. Usage: Optional
- (void)addParameterValue :(nonnull NSString *)value forKey:(NSString *)key;
/// Multiple key value custom parameters. Usage: Optional
- (void)addParameters :(nonnull NSDictionary *)parameters;
@end
NS_ASSUME_NONNULL_END
//
// ShareInviteHelper.h
// AppsFlyerLib
//
// Created by Gil Meroz on 27/01/2017.
//
//
#import <Foundation/Foundation.h>
#import "AppsFlyerLinkGenerator.h"
/**
AppsFlyerShareInviteHelper
*/
@interface AppsFlyerShareInviteHelper : NSObject
NS_ASSUME_NONNULL_BEGIN
/**
* The AppsFlyerShareInviteHelper class builds the invite URL according to various setter methods
* which allow passing on additional information on the click.
* This information is available through `onConversionDataReceived:` when the user accepts the invite and installs the app.
* In addition, campaign and channel parameters are visible within the AppsFlyer Dashboard.
*/
+ (void)generateInviteUrlWithLinkGenerator:(AppsFlyerLinkGenerator *(^)(AppsFlyerLinkGenerator *generator))generatorCreator completionHandler:(void (^)(NSURL *_Nullable url))completionHandler;
/**
* It is recommended to generate an in-app event after the invite is sent to log the invites from the senders' perspective.
* This enables you to find the users that tend most to invite friends, and the media sources that get you these users.
*/
+ (void)logInvite:(nullable NSString *)channel parameters:(nullable NSDictionary *)parameters;
@end
NS_ASSUME_NONNULL_END
framework module AppsFlyerLib {
umbrella header "AppsFlyerLib.h"
export *
module * { export * }
}
//
// CrossPromotionHelper.h
// AppsFlyerLib
//
// Created by Gil Meroz on 27/01/2017.
//
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/**
AppsFlyer allows you to log and attribute installs originating
from cross promotion campaigns of your existing apps.
Afterwards, you can optimize on your cross-promotion traffic to get even better results.
*/
@interface AppsFlyerCrossPromotionHelper : NSObject
/**
To log an impression use the following API call.
Make sure to use the promoted App ID as it appears within the AppsFlyer dashboard.
@param appID Promoted App ID
@param campaign A campaign name
@param parameters Additional params like `@{@"af_sub1": @"val", @"custom_param": @"val2" }`
*/
+ (void)logCrossPromoteImpression:(nonnull NSString *)appID
campaign:(nullable NSString *)campaign
parameters:(nullable NSDictionary *)parameters;
/**
iOS allows you to utilize the StoreKit component to open
the App Store while remaining in the context of your app.
More details at https://support.appsflyer.com/hc/en-us/articles/115004481946-Cross-Promotion-Tracking#tracking-cross-promotion-impressions
@param appID Promoted App ID
@param campaign A campaign name
@param parameters Additional params like `@{@"af_sub1": @"val", @"custom_param": @"val2" }`
@param openStoreBlock Contains promoted `clickURL`
*/
+ (void)logAndOpenStore:(nonnull NSString *)appID
campaign:(nullable NSString *)campaign
parameters:(nullable NSDictionary *)parameters
openStore:(void (^)(NSURLSession *urlSession, NSURL *clickURL))openStoreBlock;
@end
NS_ASSUME_NONNULL_END
//
// AFSDKDeeplink.h
// AppsFlyerLib
//
// Created by Andrii Hahan on 20.08.2020.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
NS_SWIFT_NAME(DeepLink)
@interface AppsFlyerDeepLink : NSObject
- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)new NS_UNAVAILABLE;
@property (readonly, nonnull) NSDictionary<NSString *, id> *clickEvent;
@property (readonly, nullable) NSString *deeplinkValue;
@property (readonly, nullable) NSString *matchType;
@property (readonly, nullable) NSString *clickHTTPReferrer;
@property (readonly, nullable) NSString *mediaSource;
@property (readonly, nullable) NSString *campaign;
@property (readonly, nullable) NSString *campaignId;
@property (readonly, nullable) NSString *afSub1;
@property (readonly, nullable) NSString *afSub2;
@property (readonly, nullable) NSString *afSub3;
@property (readonly, nullable) NSString *afSub4;
@property (readonly, nullable) NSString *afSub5;
@property (readonly) BOOL isDeferred;
- (NSString *)toString;
@end
NS_ASSUME_NONNULL_END
//
// AFSDKDeeplinkResult.h
// AppsFlyerLib
//
// Created by Andrii Hahan on 20.08.2020.
//
#import <Foundation/Foundation.h>
@class AppsFlyerDeepLink;
typedef NS_CLOSED_ENUM(NSUInteger, AFSDKDeepLinkResultStatus) {
AFSDKDeepLinkResultStatusNotFound,
AFSDKDeepLinkResultStatusFound,
AFSDKDeepLinkResultStatusFailure,
} NS_SWIFT_NAME(DeepLinkResultStatus);
NS_SWIFT_NAME(DeepLinkResult)
@interface AppsFlyerDeepLinkResult : NSObject
- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)new NS_UNAVAILABLE;
@property(readonly) AFSDKDeepLinkResultStatus status;
@property(readonly, nullable) AppsFlyerDeepLink *deepLink;
@property(readonly, nullable) NSError *error;
@end
//
// LinkGenerator.h
// AppsFlyerLib
//
// Created by Gil Meroz on 27/01/2017.
//
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/**
Payload container for the `generateInviteUrlWithLinkGenerator:completionHandler:` from `AppsFlyerShareInviteHelper`
*/
@interface AppsFlyerLinkGenerator : NSObject
/// Instance initialization is not allowed. Use generated instance
/// from `-[AppsFlyerShareInviteHelper generateInviteUrlWithLinkGenerator:completionHandler]`
- (instancetype)init NS_UNAVAILABLE;
/// Instance initialization is not allowed. Use generated instance
/// from `-[AppsFlyerShareInviteHelper generateInviteUrlWithLinkGenerator:completionHandler]`
+ (instancetype)new NS_UNAVAILABLE;
@property(nonatomic, nullable) NSString *brandDomain;
/// The channel through which the invite was sent (e.g. Facebook/Gmail/etc.). Usage: Recommended
- (void)setChannel :(nonnull NSString *)channel;
/// ReferrerCustomerId setter
- (void)setReferrerCustomerId:(nonnull NSString *)referrerCustomerId;
/// A campaign name. Usage: Optional
- (void)setCampaign :(nonnull NSString *)campaign;
/// ReferrerUID setter
- (void)setReferrerUID :(nonnull NSString *)referrerUID;
/// Referrer name
- (void)setReferrerName :(nonnull NSString *)referrerName;
/// The URL to referrer user avatar. Usage: Optional
- (void)setReferrerImageURL :(nonnull NSString *)referrerImageURL;
/// AppleAppID
- (void)setAppleAppID :(nonnull NSString *)appleAppID;
/// Deeplink path
- (void)setDeeplinkPath :(nonnull NSString *)deeplinkPath;
/// Base deeplink path
- (void)setBaseDeeplink :(nonnull NSString *)baseDeeplink;
/// A single key value custom parameter. Usage: Optional
- (void)addParameterValue :(nonnull NSString *)value forKey:(NSString *)key;
/// Multiple key value custom parameters. Usage: Optional
- (void)addParameters :(nonnull NSDictionary *)parameters;
@end
NS_ASSUME_NONNULL_END
//
// ShareInviteHelper.h
// AppsFlyerLib
//
// Created by Gil Meroz on 27/01/2017.
//
//
#import <Foundation/Foundation.h>
#import "AppsFlyerLinkGenerator.h"
/**
AppsFlyerShareInviteHelper
*/
@interface AppsFlyerShareInviteHelper : NSObject
NS_ASSUME_NONNULL_BEGIN
/**
* The AppsFlyerShareInviteHelper class builds the invite URL according to various setter methods
* which allow passing on additional information on the click.
* This information is available through `onConversionDataReceived:` when the user accepts the invite and installs the app.
* In addition, campaign and channel parameters are visible within the AppsFlyer Dashboard.
*/
+ (void)generateInviteUrlWithLinkGenerator:(AppsFlyerLinkGenerator *(^)(AppsFlyerLinkGenerator *generator))generatorCreator completionHandler:(void (^)(NSURL *_Nullable url))completionHandler;
/**
* It is recommended to generate an in-app event after the invite is sent to log the invites from the senders' perspective.
* This enables you to find the users that tend most to invite friends, and the media sources that get you these users.
*/
+ (void)logInvite:(nullable NSString *)channel parameters:(nullable NSDictionary *)parameters;
@end
NS_ASSUME_NONNULL_END
framework module AppsFlyerLib {
umbrella header "AppsFlyerLib.h"
export *
module * { export * }
}
<?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>files</key>
<dict>
<key>Headers/AppsFlyerCrossPromotionHelper.h</key>
<data>
ezewyhf50Apa+1HjqfRFE7nXZIE=
</data>
<key>Headers/AppsFlyerDeepLink.h</key>
<data>
jDznIDDggwXT7EmzE7TYcZjhMjA=
</data>
<key>Headers/AppsFlyerDeepLinkResult.h</key>
<data>
3J9juDAkVB2LUxC7/NDmKqgrzyQ=
</data>
<key>Headers/AppsFlyerLib.h</key>
<data>
mUVf5C/bLPxap0tT64QCqtDy98w=
</data>
<key>Headers/AppsFlyerLinkGenerator.h</key>
<data>
dmn7cx6Z5wxK92gRzGUwPeRiZFg=
</data>
<key>Headers/AppsFlyerShareInviteHelper.h</key>
<data>
d9/NIwpZ+CNQ8zsxhNkHTT7kpRE=
</data>
<key>Info.plist</key>
<data>
WXZiJf5d+rOTAYsiTTxkTPkPVaM=
</data>
<key>Modules/module.modulemap</key>
<data>
r+QHVTsITCgZyCe0Vpvj+KSPIWc=
</data>
</dict>
<key>files2</key>
<dict>
<key>Headers/AppsFlyerCrossPromotionHelper.h</key>
<dict>
<key>hash</key>
<data>
ezewyhf50Apa+1HjqfRFE7nXZIE=
</data>
<key>hash2</key>
<data>
YgrwrWx/ZFYjXh2t5ZHY6S0EZTroYfe5Nprl3alq+Ho=
</data>
</dict>
<key>Headers/AppsFlyerDeepLink.h</key>
<dict>
<key>hash</key>
<data>
jDznIDDggwXT7EmzE7TYcZjhMjA=
</data>
<key>hash2</key>
<data>
Z5nW/ynpNNV+krqJXqy1Gb+gdnruPFWutZYYX7hSt3I=
</data>
</dict>
<key>Headers/AppsFlyerDeepLinkResult.h</key>
<dict>
<key>hash</key>
<data>
3J9juDAkVB2LUxC7/NDmKqgrzyQ=
</data>
<key>hash2</key>
<data>
QsQGXKix5206DUBBUdDxfg5ykma/3V9MoHOxbz8NaOs=
</data>
</dict>
<key>Headers/AppsFlyerLib.h</key>
<dict>
<key>hash</key>
<data>
mUVf5C/bLPxap0tT64QCqtDy98w=
</data>
<key>hash2</key>
<data>
TZqybw725YVAAJNEa+mh2Rssna9ALVCEGy69Bwu4J8k=
</data>
</dict>
<key>Headers/AppsFlyerLinkGenerator.h</key>
<dict>
<key>hash</key>
<data>
dmn7cx6Z5wxK92gRzGUwPeRiZFg=
</data>
<key>hash2</key>
<data>
n5nvQT7mm5XE6/p92Fwks9TR1rVR9k1TgTk06A14CMg=
</data>
</dict>
<key>Headers/AppsFlyerShareInviteHelper.h</key>
<dict>
<key>hash</key>
<data>
d9/NIwpZ+CNQ8zsxhNkHTT7kpRE=
</data>
<key>hash2</key>
<data>
dcwbMQEM8N0Ugem7QbAWWGP+hfO/0vlued2Pep6IKtc=
</data>
</dict>
<key>Modules/module.modulemap</key>
<dict>
<key>hash</key>
<data>
r+QHVTsITCgZyCe0Vpvj+KSPIWc=
</data>
<key>hash2</key>
<data>
ZcaMjc66PAFkteksoe5Rzelk7opMMS8QdKiza/LgQwA=
</data>
</dict>
</dict>
<key>rules</key>
<dict>
<key>^.*</key>
<true/>
<key>^.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^version.plist$</key>
<true/>
</dict>
<key>rules2</key>
<dict>
<key>.*\.dSYM($|/)</key>
<dict>
<key>weight</key>
<real>11</real>
</dict>
<key>^(.*/)?\.DS_Store$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>2000</real>
</dict>
<key>^.*</key>
<true/>
<key>^.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^Info\.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^PkgInfo$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^embedded\.provisionprofile$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
<key>^version\.plist$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
</dict>
</dict>
</plist>
//
// CrossPromotionHelper.h
// AppsFlyerLib
//
// Created by Gil Meroz on 27/01/2017.
//
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/**
AppsFlyer allows you to log and attribute installs originating
from cross promotion campaigns of your existing apps.
Afterwards, you can optimize on your cross-promotion traffic to get even better results.
*/
@interface AppsFlyerCrossPromotionHelper : NSObject
/**
To log an impression use the following API call.
Make sure to use the promoted App ID as it appears within the AppsFlyer dashboard.
@param appID Promoted App ID
@param campaign A campaign name
@param parameters Additional params like `@{@"af_sub1": @"val", @"custom_param": @"val2" }`
*/
+ (void)logCrossPromoteImpression:(nonnull NSString *)appID
campaign:(nullable NSString *)campaign
parameters:(nullable NSDictionary *)parameters;
/**
iOS allows you to utilize the StoreKit component to open
the App Store while remaining in the context of your app.
More details at https://support.appsflyer.com/hc/en-us/articles/115004481946-Cross-Promotion-Tracking#tracking-cross-promotion-impressions
@param appID Promoted App ID
@param campaign A campaign name
@param parameters Additional params like `@{@"af_sub1": @"val", @"custom_param": @"val2" }`
@param openStoreBlock Contains promoted `clickURL`
*/
+ (void)logAndOpenStore:(nonnull NSString *)appID
campaign:(nullable NSString *)campaign
parameters:(nullable NSDictionary *)parameters
openStore:(void (^)(NSURLSession *urlSession, NSURL *clickURL))openStoreBlock;
@end
NS_ASSUME_NONNULL_END
//
// AFSDKDeeplink.h
// AppsFlyerLib
//
// Created by Andrii Hahan on 20.08.2020.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
NS_SWIFT_NAME(DeepLink)
@interface AppsFlyerDeepLink : NSObject
- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)new NS_UNAVAILABLE;
@property (readonly, nonnull) NSDictionary<NSString *, id> *clickEvent;
@property (readonly, nullable) NSString *deeplinkValue;
@property (readonly, nullable) NSString *matchType;
@property (readonly, nullable) NSString *clickHTTPReferrer;
@property (readonly, nullable) NSString *mediaSource;
@property (readonly, nullable) NSString *campaign;
@property (readonly, nullable) NSString *campaignId;
@property (readonly, nullable) NSString *afSub1;
@property (readonly, nullable) NSString *afSub2;
@property (readonly, nullable) NSString *afSub3;
@property (readonly, nullable) NSString *afSub4;
@property (readonly, nullable) NSString *afSub5;
@property (readonly) BOOL isDeferred;
- (NSString *)toString;
@end
NS_ASSUME_NONNULL_END
//
// AFSDKDeeplinkResult.h
// AppsFlyerLib
//
// Created by Andrii Hahan on 20.08.2020.
//
#import <Foundation/Foundation.h>
@class AppsFlyerDeepLink;
typedef NS_CLOSED_ENUM(NSUInteger, AFSDKDeepLinkResultStatus) {
AFSDKDeepLinkResultStatusNotFound,
AFSDKDeepLinkResultStatusFound,
AFSDKDeepLinkResultStatusFailure,
} NS_SWIFT_NAME(DeepLinkResultStatus);
NS_SWIFT_NAME(DeepLinkResult)
@interface AppsFlyerDeepLinkResult : NSObject
- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)new NS_UNAVAILABLE;
@property(readonly) AFSDKDeepLinkResultStatus status;
@property(readonly, nullable) AppsFlyerDeepLink *deepLink;
@property(readonly, nullable) NSError *error;
@end
//
// LinkGenerator.h
// AppsFlyerLib
//
// Created by Gil Meroz on 27/01/2017.
//
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/**
Payload container for the `generateInviteUrlWithLinkGenerator:completionHandler:` from `AppsFlyerShareInviteHelper`
*/
@interface AppsFlyerLinkGenerator : NSObject
/// Instance initialization is not allowed. Use generated instance
/// from `-[AppsFlyerShareInviteHelper generateInviteUrlWithLinkGenerator:completionHandler]`
- (instancetype)init NS_UNAVAILABLE;
/// Instance initialization is not allowed. Use generated instance
/// from `-[AppsFlyerShareInviteHelper generateInviteUrlWithLinkGenerator:completionHandler]`
+ (instancetype)new NS_UNAVAILABLE;
@property(nonatomic, nullable) NSString *brandDomain;
/// The channel through which the invite was sent (e.g. Facebook/Gmail/etc.). Usage: Recommended
- (void)setChannel :(nonnull NSString *)channel;
/// ReferrerCustomerId setter
- (void)setReferrerCustomerId:(nonnull NSString *)referrerCustomerId;
/// A campaign name. Usage: Optional
- (void)setCampaign :(nonnull NSString *)campaign;
/// ReferrerUID setter
- (void)setReferrerUID :(nonnull NSString *)referrerUID;
/// Referrer name
- (void)setReferrerName :(nonnull NSString *)referrerName;
/// The URL to referrer user avatar. Usage: Optional
- (void)setReferrerImageURL :(nonnull NSString *)referrerImageURL;
/// AppleAppID
- (void)setAppleAppID :(nonnull NSString *)appleAppID;
/// Deeplink path
- (void)setDeeplinkPath :(nonnull NSString *)deeplinkPath;
/// Base deeplink path
- (void)setBaseDeeplink :(nonnull NSString *)baseDeeplink;
/// A single key value custom parameter. Usage: Optional
- (void)addParameterValue :(nonnull NSString *)value forKey:(NSString *)key;
/// Multiple key value custom parameters. Usage: Optional
- (void)addParameters :(nonnull NSDictionary *)parameters;
@end
NS_ASSUME_NONNULL_END
//
// ShareInviteHelper.h
// AppsFlyerLib
//
// Created by Gil Meroz on 27/01/2017.
//
//
#import <Foundation/Foundation.h>
#import "AppsFlyerLinkGenerator.h"
/**
AppsFlyerShareInviteHelper
*/
@interface AppsFlyerShareInviteHelper : NSObject
NS_ASSUME_NONNULL_BEGIN
/**
* The AppsFlyerShareInviteHelper class builds the invite URL according to various setter methods
* which allow passing on additional information on the click.
* This information is available through `onConversionDataReceived:` when the user accepts the invite and installs the app.
* In addition, campaign and channel parameters are visible within the AppsFlyer Dashboard.
*/
+ (void)generateInviteUrlWithLinkGenerator:(AppsFlyerLinkGenerator *(^)(AppsFlyerLinkGenerator *generator))generatorCreator completionHandler:(void (^)(NSURL *_Nullable url))completionHandler;
/**
* It is recommended to generate an in-app event after the invite is sent to log the invites from the senders' perspective.
* This enables you to find the users that tend most to invite friends, and the media sources that get you these users.
*/
+ (void)logInvite:(nullable NSString *)channel parameters:(nullable NSDictionary *)parameters;
@end
NS_ASSUME_NONNULL_END
framework module AppsFlyerLib {
umbrella header "AppsFlyerLib.h"
export *
module * { export * }
}
<?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>BuildMachineOSBuild</key>
<string>20D91</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>AppsFlyerLib</string>
<key>CFBundleIdentifier</key>
<string>com.appsflyer.sdk.lib</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>AppsFlyerLib</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
<key>CFBundleVersion</key>
<string>6.2.3</string>
<key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTPlatformBuild</key>
<string>12C33</string>
<key>DTPlatformName</key>
<string>macosx</string>
<key>DTPlatformVersion</key>
<string>11.1</string>
<key>DTSDKBuild</key>
<string>20C63</string>
<key>DTSDKName</key>
<string>macosx11.1</string>
<key>DTXcode</key>
<string>1230</string>
<key>DTXcodeBuild</key>
<string>12C33</string>
<key>LSMinimumSystemVersion</key>
<string>10.15</string>
<key>UIDeviceFamily</key>
<array>
<integer>2</integer>
</array>
</dict>
</plist>
//
// CrossPromotionHelper.h
// AppsFlyerLib
//
// Created by Gil Meroz on 27/01/2017.
//
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/**
AppsFlyer allows you to log and attribute installs originating
from cross promotion campaigns of your existing apps.
Afterwards, you can optimize on your cross-promotion traffic to get even better results.
*/
@interface AppsFlyerCrossPromotionHelper : NSObject
/**
To log an impression use the following API call.
Make sure to use the promoted App ID as it appears within the AppsFlyer dashboard.
@param appID Promoted App ID
@param campaign A campaign name
@param parameters Additional params like `@{@"af_sub1": @"val", @"custom_param": @"val2" }`
*/
+ (void)logCrossPromoteImpression:(nonnull NSString *)appID
campaign:(nullable NSString *)campaign
parameters:(nullable NSDictionary *)parameters;
/**
iOS allows you to utilize the StoreKit component to open
the App Store while remaining in the context of your app.
More details at https://support.appsflyer.com/hc/en-us/articles/115004481946-Cross-Promotion-Tracking#tracking-cross-promotion-impressions
@param appID Promoted App ID
@param campaign A campaign name
@param parameters Additional params like `@{@"af_sub1": @"val", @"custom_param": @"val2" }`
@param openStoreBlock Contains promoted `clickURL`
*/
+ (void)logAndOpenStore:(nonnull NSString *)appID
campaign:(nullable NSString *)campaign
parameters:(nullable NSDictionary *)parameters
openStore:(void (^)(NSURLSession *urlSession, NSURL *clickURL))openStoreBlock;
@end
NS_ASSUME_NONNULL_END
//
// AFSDKDeeplink.h
// AppsFlyerLib
//
// Created by Andrii Hahan on 20.08.2020.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
NS_SWIFT_NAME(DeepLink)
@interface AppsFlyerDeepLink : NSObject
- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)new NS_UNAVAILABLE;
@property (readonly, nonnull) NSDictionary<NSString *, id> *clickEvent;
@property (readonly, nullable) NSString *deeplinkValue;
@property (readonly, nullable) NSString *matchType;
@property (readonly, nullable) NSString *clickHTTPReferrer;
@property (readonly, nullable) NSString *mediaSource;
@property (readonly, nullable) NSString *campaign;
@property (readonly, nullable) NSString *campaignId;
@property (readonly, nullable) NSString *afSub1;
@property (readonly, nullable) NSString *afSub2;
@property (readonly, nullable) NSString *afSub3;
@property (readonly, nullable) NSString *afSub4;
@property (readonly, nullable) NSString *afSub5;
@property (readonly) BOOL isDeferred;
- (NSString *)toString;
@end
NS_ASSUME_NONNULL_END
//
// AFSDKDeeplinkResult.h
// AppsFlyerLib
//
// Created by Andrii Hahan on 20.08.2020.
//
#import <Foundation/Foundation.h>
@class AppsFlyerDeepLink;
typedef NS_CLOSED_ENUM(NSUInteger, AFSDKDeepLinkResultStatus) {
AFSDKDeepLinkResultStatusNotFound,
AFSDKDeepLinkResultStatusFound,
AFSDKDeepLinkResultStatusFailure,
} NS_SWIFT_NAME(DeepLinkResultStatus);
NS_SWIFT_NAME(DeepLinkResult)
@interface AppsFlyerDeepLinkResult : NSObject
- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)new NS_UNAVAILABLE;
@property(readonly) AFSDKDeepLinkResultStatus status;
@property(readonly, nullable) AppsFlyerDeepLink *deepLink;
@property(readonly, nullable) NSError *error;
@end
//
// LinkGenerator.h
// AppsFlyerLib
//
// Created by Gil Meroz on 27/01/2017.
//
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/**
Payload container for the `generateInviteUrlWithLinkGenerator:completionHandler:` from `AppsFlyerShareInviteHelper`
*/
@interface AppsFlyerLinkGenerator : NSObject
/// Instance initialization is not allowed. Use generated instance
/// from `-[AppsFlyerShareInviteHelper generateInviteUrlWithLinkGenerator:completionHandler]`
- (instancetype)init NS_UNAVAILABLE;
/// Instance initialization is not allowed. Use generated instance
/// from `-[AppsFlyerShareInviteHelper generateInviteUrlWithLinkGenerator:completionHandler]`
+ (instancetype)new NS_UNAVAILABLE;
@property(nonatomic, nullable) NSString *brandDomain;
/// The channel through which the invite was sent (e.g. Facebook/Gmail/etc.). Usage: Recommended
- (void)setChannel :(nonnull NSString *)channel;
/// ReferrerCustomerId setter
- (void)setReferrerCustomerId:(nonnull NSString *)referrerCustomerId;
/// A campaign name. Usage: Optional
- (void)setCampaign :(nonnull NSString *)campaign;
/// ReferrerUID setter
- (void)setReferrerUID :(nonnull NSString *)referrerUID;
/// Referrer name
- (void)setReferrerName :(nonnull NSString *)referrerName;
/// The URL to referrer user avatar. Usage: Optional
- (void)setReferrerImageURL :(nonnull NSString *)referrerImageURL;
/// AppleAppID
- (void)setAppleAppID :(nonnull NSString *)appleAppID;
/// Deeplink path
- (void)setDeeplinkPath :(nonnull NSString *)deeplinkPath;
/// Base deeplink path
- (void)setBaseDeeplink :(nonnull NSString *)baseDeeplink;
/// A single key value custom parameter. Usage: Optional
- (void)addParameterValue :(nonnull NSString *)value forKey:(NSString *)key;
/// Multiple key value custom parameters. Usage: Optional
- (void)addParameters :(nonnull NSDictionary *)parameters;
@end
NS_ASSUME_NONNULL_END
//
// ShareInviteHelper.h
// AppsFlyerLib
//
// Created by Gil Meroz on 27/01/2017.
//
//
#import <Foundation/Foundation.h>
#import "AppsFlyerLinkGenerator.h"
/**
AppsFlyerShareInviteHelper
*/
@interface AppsFlyerShareInviteHelper : NSObject
NS_ASSUME_NONNULL_BEGIN
/**
* The AppsFlyerShareInviteHelper class builds the invite URL according to various setter methods
* which allow passing on additional information on the click.
* This information is available through `onConversionDataReceived:` when the user accepts the invite and installs the app.
* In addition, campaign and channel parameters are visible within the AppsFlyer Dashboard.
*/
+ (void)generateInviteUrlWithLinkGenerator:(AppsFlyerLinkGenerator *(^)(AppsFlyerLinkGenerator *generator))generatorCreator completionHandler:(void (^)(NSURL *_Nullable url))completionHandler;
/**
* It is recommended to generate an in-app event after the invite is sent to log the invites from the senders' perspective.
* This enables you to find the users that tend most to invite friends, and the media sources that get you these users.
*/
+ (void)logInvite:(nullable NSString *)channel parameters:(nullable NSDictionary *)parameters;
@end
NS_ASSUME_NONNULL_END
framework module AppsFlyerLib {
umbrella header "AppsFlyerLib.h"
export *
module * { export * }
}
<?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>BuildMachineOSBuild</key>
<string>20D91</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>AppsFlyerLib</string>
<key>CFBundleIdentifier</key>
<string>com.appsflyer.sdk.lib</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>AppsFlyerLib</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
<key>CFBundleVersion</key>
<string>6.2.3</string>
<key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTPlatformBuild</key>
<string>12C33</string>
<key>DTPlatformName</key>
<string>macosx</string>
<key>DTPlatformVersion</key>
<string>11.1</string>
<key>DTSDKBuild</key>
<string>20C63</string>
<key>DTSDKName</key>
<string>macosx11.1</string>
<key>DTXcode</key>
<string>1230</string>
<key>DTXcodeBuild</key>
<string>12C33</string>
<key>LSMinimumSystemVersion</key>
<string>11.1</string>
</dict>
</plist>
//
// CrossPromotionHelper.h
// AppsFlyerLib
//
// Created by Gil Meroz on 27/01/2017.
//
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/**
AppsFlyer allows you to log and attribute installs originating
from cross promotion campaigns of your existing apps.
Afterwards, you can optimize on your cross-promotion traffic to get even better results.
*/
@interface AppsFlyerCrossPromotionHelper : NSObject
/**
To log an impression use the following API call.
Make sure to use the promoted App ID as it appears within the AppsFlyer dashboard.
@param appID Promoted App ID
@param campaign A campaign name
@param parameters Additional params like `@{@"af_sub1": @"val", @"custom_param": @"val2" }`
*/
+ (void)logCrossPromoteImpression:(nonnull NSString *)appID
campaign:(nullable NSString *)campaign
parameters:(nullable NSDictionary *)parameters;
/**
iOS allows you to utilize the StoreKit component to open
the App Store while remaining in the context of your app.
More details at https://support.appsflyer.com/hc/en-us/articles/115004481946-Cross-Promotion-Tracking#tracking-cross-promotion-impressions
@param appID Promoted App ID
@param campaign A campaign name
@param parameters Additional params like `@{@"af_sub1": @"val", @"custom_param": @"val2" }`
@param openStoreBlock Contains promoted `clickURL`
*/
+ (void)logAndOpenStore:(nonnull NSString *)appID
campaign:(nullable NSString *)campaign
parameters:(nullable NSDictionary *)parameters
openStore:(void (^)(NSURLSession *urlSession, NSURL *clickURL))openStoreBlock;
@end
NS_ASSUME_NONNULL_END
//
// AFSDKDeeplink.h
// AppsFlyerLib
//
// Created by Andrii Hahan on 20.08.2020.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
NS_SWIFT_NAME(DeepLink)
@interface AppsFlyerDeepLink : NSObject
- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)new NS_UNAVAILABLE;
@property (readonly, nonnull) NSDictionary<NSString *, id> *clickEvent;
@property (readonly, nullable) NSString *deeplinkValue;
@property (readonly, nullable) NSString *matchType;
@property (readonly, nullable) NSString *clickHTTPReferrer;
@property (readonly, nullable) NSString *mediaSource;
@property (readonly, nullable) NSString *campaign;
@property (readonly, nullable) NSString *campaignId;
@property (readonly, nullable) NSString *afSub1;
@property (readonly, nullable) NSString *afSub2;
@property (readonly, nullable) NSString *afSub3;
@property (readonly, nullable) NSString *afSub4;
@property (readonly, nullable) NSString *afSub5;
@property (readonly) BOOL isDeferred;
- (NSString *)toString;
@end
NS_ASSUME_NONNULL_END
//
// AFSDKDeeplinkResult.h
// AppsFlyerLib
//
// Created by Andrii Hahan on 20.08.2020.
//
#import <Foundation/Foundation.h>
@class AppsFlyerDeepLink;
typedef NS_CLOSED_ENUM(NSUInteger, AFSDKDeepLinkResultStatus) {
AFSDKDeepLinkResultStatusNotFound,
AFSDKDeepLinkResultStatusFound,
AFSDKDeepLinkResultStatusFailure,
} NS_SWIFT_NAME(DeepLinkResultStatus);
NS_SWIFT_NAME(DeepLinkResult)
@interface AppsFlyerDeepLinkResult : NSObject
- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)new NS_UNAVAILABLE;
@property(readonly) AFSDKDeepLinkResultStatus status;
@property(readonly, nullable) AppsFlyerDeepLink *deepLink;
@property(readonly, nullable) NSError *error;
@end
//
// LinkGenerator.h
// AppsFlyerLib
//
// Created by Gil Meroz on 27/01/2017.
//
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/**
Payload container for the `generateInviteUrlWithLinkGenerator:completionHandler:` from `AppsFlyerShareInviteHelper`
*/
@interface AppsFlyerLinkGenerator : NSObject
/// Instance initialization is not allowed. Use generated instance
/// from `-[AppsFlyerShareInviteHelper generateInviteUrlWithLinkGenerator:completionHandler]`
- (instancetype)init NS_UNAVAILABLE;
/// Instance initialization is not allowed. Use generated instance
/// from `-[AppsFlyerShareInviteHelper generateInviteUrlWithLinkGenerator:completionHandler]`
+ (instancetype)new NS_UNAVAILABLE;
@property(nonatomic, nullable) NSString *brandDomain;
/// The channel through which the invite was sent (e.g. Facebook/Gmail/etc.). Usage: Recommended
- (void)setChannel :(nonnull NSString *)channel;
/// ReferrerCustomerId setter
- (void)setReferrerCustomerId:(nonnull NSString *)referrerCustomerId;
/// A campaign name. Usage: Optional
- (void)setCampaign :(nonnull NSString *)campaign;
/// ReferrerUID setter
- (void)setReferrerUID :(nonnull NSString *)referrerUID;
/// Referrer name
- (void)setReferrerName :(nonnull NSString *)referrerName;
/// The URL to referrer user avatar. Usage: Optional
- (void)setReferrerImageURL :(nonnull NSString *)referrerImageURL;
/// AppleAppID
- (void)setAppleAppID :(nonnull NSString *)appleAppID;
/// Deeplink path
- (void)setDeeplinkPath :(nonnull NSString *)deeplinkPath;
/// Base deeplink path
- (void)setBaseDeeplink :(nonnull NSString *)baseDeeplink;
/// A single key value custom parameter. Usage: Optional
- (void)addParameterValue :(nonnull NSString *)value forKey:(NSString *)key;
/// Multiple key value custom parameters. Usage: Optional
- (void)addParameters :(nonnull NSDictionary *)parameters;
@end
NS_ASSUME_NONNULL_END
//
// ShareInviteHelper.h
// AppsFlyerLib
//
// Created by Gil Meroz on 27/01/2017.
//
//
#import <Foundation/Foundation.h>
#import "AppsFlyerLinkGenerator.h"
/**
AppsFlyerShareInviteHelper
*/
@interface AppsFlyerShareInviteHelper : NSObject
NS_ASSUME_NONNULL_BEGIN
/**
* The AppsFlyerShareInviteHelper class builds the invite URL according to various setter methods
* which allow passing on additional information on the click.
* This information is available through `onConversionDataReceived:` when the user accepts the invite and installs the app.
* In addition, campaign and channel parameters are visible within the AppsFlyer Dashboard.
*/
+ (void)generateInviteUrlWithLinkGenerator:(AppsFlyerLinkGenerator *(^)(AppsFlyerLinkGenerator *generator))generatorCreator completionHandler:(void (^)(NSURL *_Nullable url))completionHandler;
/**
* It is recommended to generate an in-app event after the invite is sent to log the invites from the senders' perspective.
* This enables you to find the users that tend most to invite friends, and the media sources that get you these users.
*/
+ (void)logInvite:(nullable NSString *)channel parameters:(nullable NSDictionary *)parameters;
@end
NS_ASSUME_NONNULL_END
framework module AppsFlyerLib {
umbrella header "AppsFlyerLib.h"
export *
module * { export * }
}
//
// CrossPromotionHelper.h
// AppsFlyerLib
//
// Created by Gil Meroz on 27/01/2017.
//
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/**
AppsFlyer allows you to log and attribute installs originating
from cross promotion campaigns of your existing apps.
Afterwards, you can optimize on your cross-promotion traffic to get even better results.
*/
@interface AppsFlyerCrossPromotionHelper : NSObject
/**
To log an impression use the following API call.
Make sure to use the promoted App ID as it appears within the AppsFlyer dashboard.
@param appID Promoted App ID
@param campaign A campaign name
@param parameters Additional params like `@{@"af_sub1": @"val", @"custom_param": @"val2" }`
*/
+ (void)logCrossPromoteImpression:(nonnull NSString *)appID
campaign:(nullable NSString *)campaign
parameters:(nullable NSDictionary *)parameters;
/**
iOS allows you to utilize the StoreKit component to open
the App Store while remaining in the context of your app.
More details at https://support.appsflyer.com/hc/en-us/articles/115004481946-Cross-Promotion-Tracking#tracking-cross-promotion-impressions
@param appID Promoted App ID
@param campaign A campaign name
@param parameters Additional params like `@{@"af_sub1": @"val", @"custom_param": @"val2" }`
@param openStoreBlock Contains promoted `clickURL`
*/
+ (void)logAndOpenStore:(nonnull NSString *)appID
campaign:(nullable NSString *)campaign
parameters:(nullable NSDictionary *)parameters
openStore:(void (^)(NSURLSession *urlSession, NSURL *clickURL))openStoreBlock;
@end
NS_ASSUME_NONNULL_END
//
// AFSDKDeeplink.h
// AppsFlyerLib
//
// Created by Andrii Hahan on 20.08.2020.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
NS_SWIFT_NAME(DeepLink)
@interface AppsFlyerDeepLink : NSObject
- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)new NS_UNAVAILABLE;
@property (readonly, nonnull) NSDictionary<NSString *, id> *clickEvent;
@property (readonly, nullable) NSString *deeplinkValue;
@property (readonly, nullable) NSString *matchType;
@property (readonly, nullable) NSString *clickHTTPReferrer;
@property (readonly, nullable) NSString *mediaSource;
@property (readonly, nullable) NSString *campaign;
@property (readonly, nullable) NSString *campaignId;
@property (readonly, nullable) NSString *afSub1;
@property (readonly, nullable) NSString *afSub2;
@property (readonly, nullable) NSString *afSub3;
@property (readonly, nullable) NSString *afSub4;
@property (readonly, nullable) NSString *afSub5;
@property (readonly) BOOL isDeferred;
- (NSString *)toString;
@end
NS_ASSUME_NONNULL_END
//
// AFSDKDeeplinkResult.h
// AppsFlyerLib
//
// Created by Andrii Hahan on 20.08.2020.
//
#import <Foundation/Foundation.h>
@class AppsFlyerDeepLink;
typedef NS_CLOSED_ENUM(NSUInteger, AFSDKDeepLinkResultStatus) {
AFSDKDeepLinkResultStatusNotFound,
AFSDKDeepLinkResultStatusFound,
AFSDKDeepLinkResultStatusFailure,
} NS_SWIFT_NAME(DeepLinkResultStatus);
NS_SWIFT_NAME(DeepLinkResult)
@interface AppsFlyerDeepLinkResult : NSObject
- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)new NS_UNAVAILABLE;
@property(readonly) AFSDKDeepLinkResultStatus status;
@property(readonly, nullable) AppsFlyerDeepLink *deepLink;
@property(readonly, nullable) NSError *error;
@end
//
// LinkGenerator.h
// AppsFlyerLib
//
// Created by Gil Meroz on 27/01/2017.
//
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/**
Payload container for the `generateInviteUrlWithLinkGenerator:completionHandler:` from `AppsFlyerShareInviteHelper`
*/
@interface AppsFlyerLinkGenerator : NSObject
/// Instance initialization is not allowed. Use generated instance
/// from `-[AppsFlyerShareInviteHelper generateInviteUrlWithLinkGenerator:completionHandler]`
- (instancetype)init NS_UNAVAILABLE;
/// Instance initialization is not allowed. Use generated instance
/// from `-[AppsFlyerShareInviteHelper generateInviteUrlWithLinkGenerator:completionHandler]`
+ (instancetype)new NS_UNAVAILABLE;
@property(nonatomic, nullable) NSString *brandDomain;
/// The channel through which the invite was sent (e.g. Facebook/Gmail/etc.). Usage: Recommended
- (void)setChannel :(nonnull NSString *)channel;
/// ReferrerCustomerId setter
- (void)setReferrerCustomerId:(nonnull NSString *)referrerCustomerId;
/// A campaign name. Usage: Optional
- (void)setCampaign :(nonnull NSString *)campaign;
/// ReferrerUID setter
- (void)setReferrerUID :(nonnull NSString *)referrerUID;
/// Referrer name
- (void)setReferrerName :(nonnull NSString *)referrerName;
/// The URL to referrer user avatar. Usage: Optional
- (void)setReferrerImageURL :(nonnull NSString *)referrerImageURL;
/// AppleAppID
- (void)setAppleAppID :(nonnull NSString *)appleAppID;
/// Deeplink path
- (void)setDeeplinkPath :(nonnull NSString *)deeplinkPath;
/// Base deeplink path
- (void)setBaseDeeplink :(nonnull NSString *)baseDeeplink;
/// A single key value custom parameter. Usage: Optional
- (void)addParameterValue :(nonnull NSString *)value forKey:(NSString *)key;
/// Multiple key value custom parameters. Usage: Optional
- (void)addParameters :(nonnull NSDictionary *)parameters;
@end
NS_ASSUME_NONNULL_END
//
// ShareInviteHelper.h
// AppsFlyerLib
//
// Created by Gil Meroz on 27/01/2017.
//
//
#import <Foundation/Foundation.h>
#import "AppsFlyerLinkGenerator.h"
/**
AppsFlyerShareInviteHelper
*/
@interface AppsFlyerShareInviteHelper : NSObject
NS_ASSUME_NONNULL_BEGIN
/**
* The AppsFlyerShareInviteHelper class builds the invite URL according to various setter methods
* which allow passing on additional information on the click.
* This information is available through `onConversionDataReceived:` when the user accepts the invite and installs the app.
* In addition, campaign and channel parameters are visible within the AppsFlyer Dashboard.
*/
+ (void)generateInviteUrlWithLinkGenerator:(AppsFlyerLinkGenerator *(^)(AppsFlyerLinkGenerator *generator))generatorCreator completionHandler:(void (^)(NSURL *_Nullable url))completionHandler;
/**
* It is recommended to generate an in-app event after the invite is sent to log the invites from the senders' perspective.
* This enables you to find the users that tend most to invite friends, and the media sources that get you these users.
*/
+ (void)logInvite:(nullable NSString *)channel parameters:(nullable NSDictionary *)parameters;
@end
NS_ASSUME_NONNULL_END
framework module AppsFlyerLib {
umbrella header "AppsFlyerLib.h"
export *
module * { export * }
}
<?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>files</key>
<dict>
<key>Headers/AppsFlyerCrossPromotionHelper.h</key>
<data>
ezewyhf50Apa+1HjqfRFE7nXZIE=
</data>
<key>Headers/AppsFlyerDeepLink.h</key>
<data>
jDznIDDggwXT7EmzE7TYcZjhMjA=
</data>
<key>Headers/AppsFlyerDeepLinkResult.h</key>
<data>
3J9juDAkVB2LUxC7/NDmKqgrzyQ=
</data>
<key>Headers/AppsFlyerLib.h</key>
<data>
mUVf5C/bLPxap0tT64QCqtDy98w=
</data>
<key>Headers/AppsFlyerLinkGenerator.h</key>
<data>
dmn7cx6Z5wxK92gRzGUwPeRiZFg=
</data>
<key>Headers/AppsFlyerShareInviteHelper.h</key>
<data>
d9/NIwpZ+CNQ8zsxhNkHTT7kpRE=
</data>
<key>Info.plist</key>
<data>
5u93R98kqyvnUwhcBXH2yO7BtG0=
</data>
<key>Modules/module.modulemap</key>
<data>
r+QHVTsITCgZyCe0Vpvj+KSPIWc=
</data>
</dict>
<key>files2</key>
<dict>
<key>Headers/AppsFlyerCrossPromotionHelper.h</key>
<dict>
<key>hash</key>
<data>
ezewyhf50Apa+1HjqfRFE7nXZIE=
</data>
<key>hash2</key>
<data>
YgrwrWx/ZFYjXh2t5ZHY6S0EZTroYfe5Nprl3alq+Ho=
</data>
</dict>
<key>Headers/AppsFlyerDeepLink.h</key>
<dict>
<key>hash</key>
<data>
jDznIDDggwXT7EmzE7TYcZjhMjA=
</data>
<key>hash2</key>
<data>
Z5nW/ynpNNV+krqJXqy1Gb+gdnruPFWutZYYX7hSt3I=
</data>
</dict>
<key>Headers/AppsFlyerDeepLinkResult.h</key>
<dict>
<key>hash</key>
<data>
3J9juDAkVB2LUxC7/NDmKqgrzyQ=
</data>
<key>hash2</key>
<data>
QsQGXKix5206DUBBUdDxfg5ykma/3V9MoHOxbz8NaOs=
</data>
</dict>
<key>Headers/AppsFlyerLib.h</key>
<dict>
<key>hash</key>
<data>
mUVf5C/bLPxap0tT64QCqtDy98w=
</data>
<key>hash2</key>
<data>
TZqybw725YVAAJNEa+mh2Rssna9ALVCEGy69Bwu4J8k=
</data>
</dict>
<key>Headers/AppsFlyerLinkGenerator.h</key>
<dict>
<key>hash</key>
<data>
dmn7cx6Z5wxK92gRzGUwPeRiZFg=
</data>
<key>hash2</key>
<data>
n5nvQT7mm5XE6/p92Fwks9TR1rVR9k1TgTk06A14CMg=
</data>
</dict>
<key>Headers/AppsFlyerShareInviteHelper.h</key>
<dict>
<key>hash</key>
<data>
d9/NIwpZ+CNQ8zsxhNkHTT7kpRE=
</data>
<key>hash2</key>
<data>
dcwbMQEM8N0Ugem7QbAWWGP+hfO/0vlued2Pep6IKtc=
</data>
</dict>
<key>Modules/module.modulemap</key>
<dict>
<key>hash</key>
<data>
r+QHVTsITCgZyCe0Vpvj+KSPIWc=
</data>
<key>hash2</key>
<data>
ZcaMjc66PAFkteksoe5Rzelk7opMMS8QdKiza/LgQwA=
</data>
</dict>
</dict>
<key>rules</key>
<dict>
<key>^.*</key>
<true/>
<key>^.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^version.plist$</key>
<true/>
</dict>
<key>rules2</key>
<dict>
<key>.*\.dSYM($|/)</key>
<dict>
<key>weight</key>
<real>11</real>
</dict>
<key>^(.*/)?\.DS_Store$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>2000</real>
</dict>
<key>^.*</key>
<true/>
<key>^.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^Info\.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^PkgInfo$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^embedded\.provisionprofile$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
<key>^version\.plist$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
</dict>
</dict>
</plist>
This source diff could not be displayed because it is too large. You can view the blob instead.
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