Skip to content

Commit 7fee79a

Browse files
authored
Merge pull request #638 from adjust/v4330
Version 4.33.0
2 parents a7b50f1 + ababcb2 commit 7fee79a

File tree

256 files changed

+2456
-1637
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

256 files changed

+2456
-1637
lines changed

Adjust.podspec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
Pod::Spec.new do |s|
22
s.name = "Adjust"
3-
s.version = "4.32.1"
3+
s.version = "4.33.0"
44
s.summary = "This is the iOS SDK of adjust. You can read more about it at http://adjust.com."
55
s.homepage = "https://github.com/adjust/ios_sdk"
66
s.license = { :type => 'MIT', :file => 'MIT-LICENSE' }
77
s.author = { "Adjust GmbH" => "[email protected]" }
8-
s.source = { :git => "https://github.com/adjust/ios_sdk.git", :tag => "v4.32.1" }
8+
s.source = { :git => "https://github.com/adjust/ios_sdk.git", :tag => "v4.33.0" }
99
s.ios.deployment_target = '9.0'
1010
s.tvos.deployment_target = '9.0'
1111
s.framework = 'SystemConfiguration'

Adjust.xcodeproj/project.pbxproj

Lines changed: 48 additions & 0 deletions
Large diffs are not rendered by default.

Adjust/ADJActivityHandler.m

Lines changed: 34 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#import "ADJSdkClickHandler.h"
2323
#import "ADJUserDefaults.h"
2424
#import "ADJUrlStrategy.h"
25+
#import "ADJSKAdNetwork.h"
2526

2627
NSString * const ADJiAdPackageKey = @"iad3";
2728
NSString * const ADJAdServicesPackageKey = @"apple_ads";
@@ -173,11 +174,11 @@ - (id)initWithConfig:(ADJConfig *)adjustConfig
173174
[self readActivityState];
174175

175176
// register SKAdNetwork attribution if we haven't already
176-
if ([ADJUserDefaults getSkadRegisterCallTimestamp] == nil) {
177-
[self registerForSKAdNetworkAttribution];
178-
} else {
179-
[ADJAdjustFactory.logger debug:@"Call to SKAdNetwork's registerAppForAdNetworkAttribution method already made for this install"];
180-
}
177+
[[ADJSKAdNetwork getInstance] adjRegisterWithCompletionHandler:^(NSError * _Nonnull error) {
178+
if (error) {
179+
// handle error
180+
}
181+
}];
181182

182183
self.internalState = [[ADJInternalState alloc] init];
183184

@@ -2835,32 +2836,6 @@ - (BOOL)checkAdRevenueI:(ADJActivityHandler *)selfI
28352836
return YES;
28362837
}
28372838

2838-
- (void)registerForSKAdNetworkAttribution {
2839-
if (!self.adjustConfig.isSKAdNetworkHandlingActive) {
2840-
return;
2841-
}
2842-
id<ADJLogger> logger = [ADJAdjustFactory logger];
2843-
2844-
Class skAdNetwork = NSClassFromString(@"SKAdNetwork");
2845-
if (skAdNetwork == nil) {
2846-
[logger warn:@"StoreKit framework not found in the app (SKAdNetwork not found)"];
2847-
return;
2848-
}
2849-
2850-
SEL registerAttributionSelector = NSSelectorFromString(@"registerAppForAdNetworkAttribution");
2851-
if ([skAdNetwork respondsToSelector:registerAttributionSelector]) {
2852-
#pragma clang diagnostic push
2853-
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
2854-
[skAdNetwork performSelector:registerAttributionSelector];
2855-
#pragma clang diagnostic pop
2856-
[logger verbose:@"Call to SKAdNetwork's registerAppForAdNetworkAttribution method made"];
2857-
2858-
// store timestamp of when register call was successfully made
2859-
NSDate *callTime = [NSDate date];
2860-
[ADJUserDefaults saveSkadRegisterCallTimestamp:callTime];
2861-
}
2862-
}
2863-
28642839
- (void)checkConversionValue:(ADJResponseData *)responseData {
28652840
if (!self.adjustConfig.isSKAdNetworkHandlingActive) {
28662841
return;
@@ -2870,19 +2845,38 @@ - (void)checkConversionValue:(ADJResponseData *)responseData {
28702845
}
28712846

28722847
NSNumber *conversionValue = [responseData.jsonResponse objectForKey:@"skadn_conv_value"];
2873-
28742848
if (!conversionValue) {
28752849
return;
28762850
}
2877-
2878-
[ADJUtil updateSkAdNetworkConversionValue:conversionValue];
28792851

2880-
if ([self.adjustDelegate respondsToSelector:@selector(adjustConversionValueUpdated:)]) {
2881-
[self.logger debug:@"Launching conversion value updated delegate"];
2882-
[ADJUtil launchInMainThread:self.adjustDelegate
2883-
selector:@selector(adjustConversionValueUpdated:)
2884-
withObject:conversionValue];
2885-
}
2852+
NSString *coarseValue = [responseData.jsonResponse objectForKey:@"skadn_coarse_value"];
2853+
NSNumber *lockWindow = [responseData.jsonResponse objectForKey:@"skadn_lock_window"];
2854+
2855+
[[ADJSKAdNetwork getInstance] adjUpdateConversionValue:[conversionValue intValue]
2856+
coarseValue:coarseValue
2857+
lockWindow:lockWindow
2858+
completionHandler:^(NSError *error) {
2859+
if (error) {
2860+
// handle error
2861+
} else {
2862+
// ping old callback if implemented
2863+
if ([self.adjustDelegate respondsToSelector:@selector(adjustConversionValueUpdated:)]) {
2864+
[self.logger debug:@"Launching adjustConversionValueUpdated: delegate"];
2865+
[ADJUtil launchInMainThread:self.adjustDelegate
2866+
selector:@selector(adjustConversionValueUpdated:)
2867+
withObject:conversionValue];
2868+
}
2869+
// ping new callback if implemented
2870+
if ([self.adjustDelegate respondsToSelector:@selector(adjustConversionValueUpdated:coarseValue:lockWindow:)]) {
2871+
[self.logger debug:@"Launching adjustConversionValueUpdated:coarseValue:lockWindow: delegate"];
2872+
[ADJUtil launchInMainThread:^{
2873+
[self.adjustDelegate adjustConversionValueUpdated:conversionValue
2874+
coarseValue:coarseValue
2875+
lockWindow:lockWindow];
2876+
}];
2877+
}
2878+
}
2879+
}];
28862880
}
28872881

28882882
- (void)updateAttStatusFromUserCallback:(int)newAttStatusFromUser {

Adjust/ADJConfig.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,25 @@
7777
- (BOOL)adjustDeeplinkResponse:(nullable NSURL *)deeplink;
7878

7979
/**
80-
* @brief Optional delegate method that gets called when Adjust SDK sets conversion value for the user.
80+
* @brief Optional SKAdNetwork pre 4.0 style delegate method that gets called when Adjust SDK sets conversion value for the user.
8181
*
8282
* @param conversionValue Conversion value used by Adjust SDK to invoke updateConversionValue: API.
8383
*/
8484
- (void)adjustConversionValueUpdated:(nullable NSNumber *)conversionValue;
8585

86+
/**
87+
* @brief Optional SKAdNetwork 4.0 style delegate method that gets called when Adjust SDK sets conversion value for the user.
88+
* You can use this callback even with using pre 4.0 SKAdNetwork.
89+
* In that case you can expect coarseValue and lockWindow values to be nil.
90+
*
91+
* @param fineValue Conversion value set by Adjust SDK.
92+
* @param coarseValue Coarse value set by Adjust SDK.
93+
* @param lockWindow Lock window set by Adjust SDK.
94+
*/
95+
- (void)adjustConversionValueUpdated:(nullable NSNumber *)fineValue
96+
coarseValue:(nullable NSString *)coarseValue
97+
lockWindow:(nullable NSNumber *)lockWindow;
98+
8699
@end
87100

88101
/**

Adjust/ADJSKAdNetwork.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//
2+
// ADJSKAdNetwork.h
3+
// Adjust
4+
//
5+
// Created by Uglješa Erceg (@uerceg) on 27th October 2022.
6+
// Copyright © 2022-Present Adjust GmbH. All rights reserved.
7+
//
8+
9+
#import <Foundation/Foundation.h>
10+
11+
NS_ASSUME_NONNULL_BEGIN
12+
13+
@interface ADJSKAdNetwork : NSObject
14+
15+
+ (nullable instancetype)getInstance;
16+
17+
- (void)registerAppForAdNetworkAttribution;
18+
19+
- (void)updateConversionValue:(NSInteger)conversionValue;
20+
21+
- (void)updatePostbackConversionValue:(NSInteger)conversionValue
22+
completionHandler:(void (^)(NSError *error))completion;
23+
24+
- (void)updatePostbackConversionValue:(NSInteger)fineValue
25+
coarseValue:(NSString *)coarseValue
26+
completionHandler:(void (^)(NSError *error))completion;
27+
28+
- (void)updatePostbackConversionValue:(NSInteger)fineValue
29+
coarseValue:(NSString *)coarseValue
30+
lockWindow:(BOOL)lockWindow
31+
completionHandler:(void (^)(NSError *error))completion;
32+
33+
- (void)adjRegisterWithCompletionHandler:(void (^)(NSError *error))callback;
34+
35+
- (void)adjUpdateConversionValue:(NSInteger)conversionValue
36+
coarseValue:(NSString *)coarseValue
37+
lockWindow:(NSNumber *)lockWindow
38+
completionHandler:(void (^)(NSError *error))callback;
39+
40+
@end
41+
42+
NS_ASSUME_NONNULL_END

Adjust/ADJSKAdNetwork.m

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
//
2+
// ADJSKAdNetwork.m
3+
// Adjust
4+
//
5+
// Created by Uglješa Erceg on 27.10.22.
6+
// Copyright © 2022 Adjust GmbH. All rights reserved.
7+
//
8+
9+
#include <dlfcn.h>
10+
11+
#import "ADJSKAdNetwork.h"
12+
#import "ADJUserDefaults.h"
13+
#import "ADJAdjustFactory.h"
14+
#import "ADJLogger.h"
15+
16+
@interface ADJSKAdNetwork()
17+
18+
@property (nonatomic, weak) id<ADJLogger> logger;
19+
@property (nonatomic, strong) Class clsSkAdNetwork;
20+
@property (nonatomic, assign) SEL selRegisterAppForAdNetworkAttribution;
21+
@property (nonatomic, assign) SEL selUpdateConversionValue;
22+
@property (nonatomic, assign) SEL selUpdatePostbackConversionValueCompletionHandler;
23+
@property (nonatomic, assign) SEL selUpdatePostbackConversionValueCoarseValueCompletionHandler;
24+
@property (nonatomic, assign) SEL selUpdatePostbackConversionValueCoarseValueLockWindowCompletionHandler;
25+
26+
@end
27+
28+
@implementation ADJSKAdNetwork
29+
30+
#pragma mark - Lifecycle
31+
32+
+ (instancetype)getInstance {
33+
static ADJSKAdNetwork *defaultInstance = nil;
34+
static dispatch_once_t onceToken = 0;
35+
dispatch_once(&onceToken, ^{
36+
defaultInstance = [[self alloc] init];
37+
});
38+
return defaultInstance;
39+
}
40+
41+
- (instancetype)init {
42+
self = [super init];
43+
if (self == nil) {
44+
return nil;
45+
}
46+
47+
self.logger = [ADJAdjustFactory logger];
48+
self.clsSkAdNetwork = NSClassFromString(@"SKAdNetwork");
49+
self.selRegisterAppForAdNetworkAttribution = NSSelectorFromString(@"registerAppForAdNetworkAttribution");
50+
self.selUpdateConversionValue = NSSelectorFromString(@"updateConversionValue:");
51+
self.selUpdatePostbackConversionValueCompletionHandler = NSSelectorFromString(@"updatePostbackConversionValue:completionHandler:");
52+
self.selUpdatePostbackConversionValueCoarseValueCompletionHandler = NSSelectorFromString(@"updatePostbackConversionValue:coarseValue:completionHandler:");
53+
self.selUpdatePostbackConversionValueCoarseValueLockWindowCompletionHandler = NSSelectorFromString(@"updatePostbackConversionValue:coarseValue:lockWindow:completionHandler:");
54+
55+
return self;
56+
}
57+
58+
#pragma mark - SKAdNetwork API
59+
60+
- (void)registerAppForAdNetworkAttribution {
61+
if (@available(iOS 14.0, *)) {
62+
if ([self isStoreKitAvailable]) {
63+
((id (*)(id, SEL))[self.clsSkAdNetwork methodForSelector:self.selRegisterAppForAdNetworkAttribution])(self.clsSkAdNetwork, self.selRegisterAppForAdNetworkAttribution);
64+
[self.logger debug:@"Called SKAdNetwork's registerAppForAdNetworkAttribution method"];
65+
}
66+
} else {
67+
[self.logger warn:@"SKAdNetwork's registerAppForAdNetworkAttribution method not available for this operating system version"];
68+
}
69+
}
70+
71+
- (void)updateConversionValue:(NSInteger)conversionValue {
72+
if (@available(iOS 14.0, *)) {
73+
if ([self isStoreKitAvailable]) {
74+
((id (*)(id, SEL, NSInteger))[self.clsSkAdNetwork methodForSelector:self.selUpdateConversionValue])(self.clsSkAdNetwork, self.selUpdateConversionValue, conversionValue);
75+
[self.logger verbose:@"Called SKAdNetwork's updateConversionValue: method made with conversion value: %d", conversionValue];
76+
}
77+
} else {
78+
[self.logger warn:@"SKAdNetwork's updateConversionValue: method not available for this operating system version"];
79+
}
80+
}
81+
82+
- (void)updatePostbackConversionValue:(NSInteger)conversionValue
83+
completionHandler:(void (^)(NSError *error))completion {
84+
if (@available(iOS 15.4, *)) {
85+
if ([self isStoreKitAvailable]) {
86+
((id (*)(id, SEL, NSInteger, void (^)(NSError *error)))[self.clsSkAdNetwork methodForSelector:self.selUpdatePostbackConversionValueCompletionHandler])(self.clsSkAdNetwork, self.selUpdatePostbackConversionValueCompletionHandler, conversionValue, completion);
87+
// call is made, success / failure will be checked and logged inside of the completion block
88+
}
89+
} else {
90+
[self.logger warn:@"SKAdNetwork's updatePostbackConversionValue:completionHandler: method not available for this operating system version"];
91+
}
92+
}
93+
94+
- (void)updatePostbackConversionValue:(NSInteger)fineValue
95+
coarseValue:(NSString *)coarseValue
96+
completionHandler:(void (^)(NSError *error))completion {
97+
if (@available(iOS 16.1, *)) {
98+
if ([self isStoreKitAvailable]) {
99+
((id (*)(id, SEL, NSInteger, NSString *, void (^)(NSError *error)))[self.clsSkAdNetwork methodForSelector:self.selUpdatePostbackConversionValueCoarseValueCompletionHandler])(self.clsSkAdNetwork, self.selUpdatePostbackConversionValueCoarseValueCompletionHandler, fineValue, coarseValue, completion);
100+
// call is made, success / failure will be checked and logged inside of the completion block
101+
}
102+
} else {
103+
[self.logger warn:@"SKAdNetwork's updatePostbackConversionValue:coarseValue:completionHandler: method not available for this operating system version"];
104+
}
105+
}
106+
107+
- (void)updatePostbackConversionValue:(NSInteger)fineValue
108+
coarseValue:(NSString *)coarseValue
109+
lockWindow:(BOOL)lockWindow
110+
completionHandler:(void (^)(NSError *error))completion {
111+
if (@available(iOS 16.1, *)) {
112+
if ([self isStoreKitAvailable]) {
113+
((id (*)(id, SEL, NSInteger, NSString *, BOOL, void (^)(NSError *error)))[self.clsSkAdNetwork methodForSelector:self.selUpdatePostbackConversionValueCoarseValueLockWindowCompletionHandler])(self.clsSkAdNetwork, self.selUpdatePostbackConversionValueCoarseValueLockWindowCompletionHandler, fineValue, coarseValue, lockWindow, completion);
114+
// call is made, success / failure will be checked and logged inside of the completion block
115+
}
116+
} else {
117+
[self.logger warn:@"SKAdNetwork's updatePostbackConversionValue:coarseValue:lockWindow:completionHandler: method not available for this operating system version"];
118+
}
119+
}
120+
121+
#pragma mark - Adjust helper methods
122+
123+
- (void)adjRegisterWithCompletionHandler:(void (^)(NSError *error))callback {
124+
if ([ADJUserDefaults getSkadRegisterCallTimestamp] != nil) {
125+
[self.logger debug:@"Call to register app with SKAdNetwork already made for this install"];
126+
callback(nil);
127+
return;
128+
}
129+
[self registerAppForAdNetworkAttribution];
130+
callback(nil);
131+
[self writeSkAdNetworkRegisterCallTimestamp];
132+
}
133+
134+
- (void)adjUpdateConversionValue:(NSInteger)conversionValue
135+
coarseValue:(NSString *)coarseValue
136+
lockWindow:(NSNumber *)lockWindow
137+
completionHandler:(void (^)(NSError *error))callback {
138+
if (coarseValue != nil && lockWindow != nil) {
139+
// 4.0 world
140+
[self updatePostbackConversionValue:conversionValue
141+
coarseValue:[self getSkAdNetworkCoarseConversionValue:coarseValue]
142+
lockWindow:[lockWindow boolValue]
143+
completionHandler:^(NSError * _Nonnull error) {
144+
if (error) {
145+
[self.logger error:@"Call to SKAdNetwork's updatePostbackConversionValue:coarseValue:lockWindow:completionHandler: method with conversion value: %d, coarse value: %@, lock window: %d failed\nDescription: %@", conversionValue, coarseValue, [lockWindow boolValue], error.localizedDescription];
146+
} else {
147+
[self.logger debug:@"Called SKAdNetwork's updatePostbackConversionValue:coarseValue:lockWindow:completionHandler: method with conversion value: %d, coarse value: %@, lock window: %d", conversionValue, coarseValue, [lockWindow boolValue]];
148+
}
149+
callback(error);
150+
}];
151+
} else {
152+
// pre 4.0 world
153+
if (@available(iOS 15.4, *)) {
154+
[self updatePostbackConversionValue:conversionValue
155+
completionHandler:^(NSError * _Nonnull error) {
156+
if (error) {
157+
[self.logger error:@"Call to updatePostbackConversionValue:completionHandler: method with conversion value: %d failed\nDescription: %@", conversionValue, error.localizedDescription];
158+
} else {
159+
[self.logger debug:@"Called SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %d", conversionValue];
160+
}
161+
callback(error);
162+
}];
163+
} else if (@available(iOS 14.0, *)) {
164+
[self updateConversionValue:conversionValue];
165+
callback(nil);
166+
} else {
167+
[self.logger error:@"SKAdNetwork API not available on this iOS version"];
168+
callback(nil);
169+
}
170+
}
171+
}
172+
173+
#pragma mark - Private
174+
175+
- (BOOL)isStoreKitAvailable {
176+
if (self.clsSkAdNetwork == nil) {
177+
[self.logger warn:@"StoreKit.framework not found in the app (SKAdNetwork class not found)"];
178+
return NO;
179+
}
180+
return YES;
181+
}
182+
183+
- (void)writeSkAdNetworkRegisterCallTimestamp {
184+
NSDate *callTime = [NSDate date];
185+
[ADJUserDefaults saveSkadRegisterCallTimestamp:callTime];
186+
}
187+
188+
- (NSString *)getSkAdNetworkCoarseConversionValue:(NSString *)adjustCoarseValue {
189+
if (@available(iOS 16.1, *)) {
190+
if ([adjustCoarseValue isEqualToString:@"low"]) {
191+
NSString * __autoreleasing *lowValue = (NSString * __autoreleasing *)dlsym(RTLD_DEFAULT, "SKAdNetworkCoarseConversionValueLow");
192+
return *lowValue;
193+
} else if ([adjustCoarseValue isEqualToString:@"medium"]) {
194+
NSString * __autoreleasing *mediumValue = (NSString * __autoreleasing *)dlsym(RTLD_DEFAULT, "SKAdNetworkCoarseConversionValueMedium");
195+
return *mediumValue;
196+
} else if ([adjustCoarseValue isEqualToString:@"high"]) {
197+
NSString * __autoreleasing *highValue = (NSString * __autoreleasing *)dlsym(RTLD_DEFAULT, "SKAdNetworkCoarseConversionValueHigh");
198+
return *highValue;
199+
} else {
200+
return nil;
201+
}
202+
} else {
203+
return nil;
204+
}
205+
}
206+
207+
@end

0 commit comments

Comments
 (0)