diff --git a/VWO.xcworkspace/xcshareddata/swiftpm/Package.resolved b/VWO.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 00000000..b448b27c --- /dev/null +++ b/VWO.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,32 @@ +{ + "pins" : [ + { + "identity" : "socket.io-client-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/socketio/socket.io-client-swift", + "state" : { + "revision" : "36db2ff0ebc7239187f9b382fd318e122da71caa", + "version" : "15.2.0" + } + }, + { + "identity" : "starscream", + "kind" : "remoteSourceControl", + "location" : "https://github.com/daltoniam/Starscream", + "state" : { + "revision" : "e6b65c6d9077ea48b4a7bdda8994a1d3c6969c8d", + "version" : "3.1.1" + } + }, + { + "identity" : "swift-nio-zlib-support", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-zlib-support.git", + "state" : { + "revision" : "37760e9a52030bb9011972c5213c3350fa9d41fd", + "version" : "1.0.0" + } + } + ], + "version" : 2 +} diff --git a/VWO/Models/VWOCampaign.h b/VWO/Models/VWOCampaign.h index 8c37fbe4..1ed6445d 100644 --- a/VWO/Models/VWOCampaign.h +++ b/VWO/Models/VWOCampaign.h @@ -31,6 +31,7 @@ typedef NS_ENUM(NSInteger, CampaignStatus) { - (nullable instancetype)initWithDictionary:(NSDictionary *)campaignDict; - (nullable id)variationForKey:(NSString *)key; +- (nullable id)testKey:(NSString *)testKey; - (nullable VWOGoal *)goalForIdentifier:(NSString *)identifier; @end diff --git a/VWO/Models/VWOCampaign.m b/VWO/Models/VWOCampaign.m index fc752819..adf9c8fb 100644 --- a/VWO/Models/VWOCampaign.m +++ b/VWO/Models/VWOCampaign.m @@ -81,6 +81,11 @@ - (nullable instancetype)initWithDictionary:(NSDictionary *) campaignDict { return self; } +- (nullable id)testKey:(NSString *)testKey { + NSParameterAssert(testKey); + //If key does not exist then NSDictionary returns nil + return self.testKey; +} - (nullable id)variationForKey:(NSString *)key { NSParameterAssert(key); //If key does not exist then NSDictionary returns nil diff --git a/VWO/VWO.h b/VWO/VWO.h index fdf96392..ab8b32d5 100644 --- a/VWO/VWO.h +++ b/VWO/VWO.h @@ -143,6 +143,20 @@ __deprecated_msg("Use objectForKey:defaultValue instead"); */ + (BOOL)boolForKey:(NSString *)key defaultValue:(BOOL)defaultValue NS_SWIFT_NAME(boolFor(key:defaultValue:)); +/** + Fetch variation for given key + + @param key key whose value is to be fetched + + @param defaultValue Value that is to be returned if key is not found + + @param testKey Value is Test key which is used with the variation Key + + @return variation if available else `defaultValue` + */ ++ (BOOL)boolForKey:(NSString *)key defaultValue:(BOOL)defaultValue testKey:(NSString *)testKey NS_SWIFT_NAME(boolFor(key:defaultValue:testKey:)); + + /** Fetch variation for given key @@ -154,6 +168,19 @@ __deprecated_msg("Use objectForKey:defaultValue instead"); */ + (int)intForKey:(NSString *)key defaultValue:(int)defaultValue NS_SWIFT_NAME(intFor(key:defaultValue:)); +/** + Fetch variation for given key + + @param key key whose value is to be fetched + + @param defaultValue Value that is to be returned if key is not found + + @param testKey Value is Test key which is used with the variation Key + + @return variation if available else `defaultValue` + */ ++ (int)intForKey:(NSString *)key defaultValue:(int)defaultValue testKey:(NSString *)testKey NS_SWIFT_NAME(intFor(key:defaultValue:testKey:)); + /** Fetch variation for given key @@ -165,6 +192,19 @@ __deprecated_msg("Use objectForKey:defaultValue instead"); */ + (double)doubleForKey:(NSString *)key defaultValue:(double)defaultValue NS_SWIFT_NAME(doubleFor(key:defaultValue:)); +/** + Fetch variation for given key + + @param key key whose value is to be fetched + + @param defaultValue Value that is to be returned if key is not found + + @param testKey Value is Test key which is used with the variation Key + + @return variation if available else `defaultValue` + */ ++ (double)doubleForKey:(NSString *)key defaultValue:(double)defaultValue testKey:(NSString *)testKey NS_SWIFT_NAME(doubleFor(key:defaultValue:testKey:)); + /** Fetch variation for given key @@ -176,6 +216,19 @@ __deprecated_msg("Use objectForKey:defaultValue instead"); */ + (nullable NSString *)stringForKey:(NSString *)key defaultValue:(nullable NSString *)defaultValue NS_SWIFT_NAME(stringFor(key:defaultValue:)); +/** + Fetch variation for given key + + @param key key whose value is to be fetched + + @param defaultValue Value that is to be returned if key is not found + + @param testKey Value is Test key which is used with the variation Key + + @return variation if available else `defaultValue` + */ ++ (nullable NSString *)stringForKey:(NSString *)key defaultValue:(nullable NSString *)defaultValue testKey:(NSString *)testKey NS_SWIFT_NAME(stringFor(key:defaultValue:testKey:)); + /** Fetch variation name for given campaign. diff --git a/VWO/VWO.m b/VWO/VWO.m index fccec85b..d82154c3 100644 --- a/VWO/VWO.m +++ b/VWO/VWO.m @@ -110,20 +110,33 @@ + (void)launchSynchronouslyForAPIKey:(NSString *)apiKey }); } -+ (id)objectForKey:(NSString *)key { ++ (id)objectForKey:(NSString *)key{ NSParameterAssert(key); __block id object; dispatch_barrier_sync(VWOController.taskQueue, ^{ - object = [VWOController.shared variationForKey:key];; + object = [VWOController.shared variationForKey:key]; }); return object; } -+ (id)objectForKey:(NSString *)key defaultValue:(nullable id)defaultValue { ++ (id)objectForKey:(NSString *)key testKey:(NSString *)testKey{ + NSParameterAssert(key); + __block id object; + dispatch_barrier_sync(VWOController.taskQueue, ^{ + object = [VWOController.shared variationForKey:key testKey:testKey]; + }); + return object; +} ++ (id)objectForKey:(NSString *)key defaultValue:(nullable id)defaultValue{ id object = [self objectForKey:key]; return object != nil ? object : defaultValue; } ++ (id)objectForKey:(NSString *)key defaultValue:(nullable id)defaultValue testKey:(NSString *)testKey{ + id object = [self objectForKey:key testKey:testKey]; + return object != nil ? object : defaultValue; +} + + (id)variationForKey:(NSString *)key defaultValue:(id)defaultValue { // Deprecated return [self objectForKey:key defaultValue:defaultValue]; @@ -134,22 +147,43 @@ + (BOOL)boolForKey:(NSString *)key defaultValue:(BOOL)defaultValue { return object != nil ? [object boolValue] : defaultValue; } ++ (BOOL)boolForKey:(NSString *)key defaultValue:(BOOL)defaultValue testKey:(NSString *)testKey{ + id object = [self objectForKey:key testKey:testKey]; + return object != nil ? [object boolValue] : defaultValue; +} + + (int)intForKey:(NSString *)key defaultValue:(int)defaultValue { id object = [self objectForKey:key]; return object != nil ? [object intValue] : defaultValue; } ++ (int)intForKey:(NSString *)key defaultValue:(int)defaultValue testKey:(NSString *)testKey{ + id object = [self objectForKey:key testKey:testKey]; + return object != nil ? [object intValue] : defaultValue; +} + + (double)doubleForKey:(NSString *)key defaultValue:(double)defaultValue { id object = [self objectForKey:key]; return object != nil ? [object doubleValue] : defaultValue; } ++ (double)doubleForKey:(NSString *)key defaultValue:(double)defaultValue testKey:(NSString *)testKey{ + id object = [self objectForKey:key testKey:testKey]; + return object != nil ? [object doubleValue] : defaultValue; +} + + (NSString *)stringForKey:(NSString *)key defaultValue:(NSString *)defaultValue { NSParameterAssert(key); id object = [self objectForKey:key]; return [NSString stringWithFormat:@"%@", object != nil ? object : defaultValue]; } ++ (NSString *)stringForKey:(NSString *)key defaultValue:(NSString *)defaultValue testKey:(NSString *)testKey{ + NSParameterAssert(key); + id object = [self objectForKey:key testKey:testKey]; + return [NSString stringWithFormat:@"%@", object != nil ? object : defaultValue]; +} + + (nullable NSString *)variationNameForTestKey:(NSString *)campaignTestKey { NSParameterAssert(campaignTestKey); __block NSString *variationName; diff --git a/VWO/VWOController.h b/VWO/VWOController.h index c6c525f2..7bdae432 100644 --- a/VWO/VWOController.h +++ b/VWO/VWOController.h @@ -37,6 +37,7 @@ static NSString *kVWOSDKversion = @"2.10.0"; - (void)trackConversion:(NSString *)goal withValue:(nullable NSNumber *)value; - (nullable id)variationForKey:(NSString *)key; +- (nullable id)variationForKey:(NSString *)key testKey:(NSString *)testKey; - (nullable NSString *)variationNameForCampaignTestKey:(NSString *)campaignTestKey; - (void)pushCustomDimension:(NSString *) customDimensionKey withCustomDimensionValue:(NSString *) customDimensionValue; diff --git a/VWO/VWOController.m b/VWO/VWOController.m index ad83a370..7675bdb6 100644 --- a/VWO/VWOController.m +++ b/VWO/VWOController.m @@ -266,6 +266,52 @@ - (id)variationForKey:(NSString *)key { return finalVariation; } +- (id)variationForKey:(NSString *)key testKey:(NSString *)testKey{ + if (!_initialised) { + VWOLogWarning(@"variationForKey(%@) called before launching VWO", key); + return nil; + } + + if (VWOSocketConnector.isConnectedToBrowser) { + if(key && _previewInfo != nil) { + VWOLogInfo(@"Socket: got variation %@ for key %@", _previewInfo[key], key); + return _previewInfo[key]; + } + VWOLogInfo(@"Socket: got variation nil for key %@", key); + return nil; + } + + id finalVariation = nil; + for (VWOCampaign *campaign in _campaignList) { + id variation = [campaign variationForKey:key]; + + BOOL isCampaignTracked = [VWOUserDefaults isTrackingUserForCampaign:campaign]; + + id campaginTestKey = [campaign testKey:testKey]; + if(campaginTestKey){ + NSString * campTestKey = campaginTestKey; + //If variation Key is present in Campaign and testKey matches + if (variation && [campTestKey isEqualToString:testKey]) { + if (isCampaignTracked) { + finalVariation = variation; + } else { + VWOSegmentEvaluator *evaluator = [VWOSegmentEvaluator makeEvaluator:_customVariables]; + BOOL canBePart = [evaluator canUserBePartOfCampaignForSegment:campaign.segmentObject]; + if (canBePart) { + finalVariation = variation; + [self trackUserForCampaign:campaign]; + } + } + } + } + } + if (finalVariation == [NSNull null]) { + // finalVariation can be NSNull if Control is assigned to campaign + return nil; + } + VWOLogDebug(@"Got variation %@ for key %@", finalVariation, key); + return finalVariation; +} - (nullable NSString *)variationNameForCampaignTestKey:(NSString *)campaignTestKey { if (!_initialised) { VWOLogWarning(@"variationNameForCampaignTestKey(%@) called before launching VWO", campaignTestKey); diff --git a/VWO/VWOURL.m b/VWO/VWOURL.m index d3a8638f..ac45d101 100644 --- a/VWO/VWOURL.m +++ b/VWO/VWOURL.m @@ -109,7 +109,7 @@ - (NSURL *)forMakingUserPartOfCampaign:(VWOCampaign *)campaign @"u" : VWOUserDefaults.UUID, @"s" : [NSString stringWithFormat:@"%lu", (unsigned long)VWOUserDefaults.sessionCount], @"random" : [self randomNumber], - @"sId" : [NSString stringWithFormat:@"%f", date.timeIntervalSince1970], + @"sId" : [NSString stringWithFormat:@"%lu", (unsigned long)date.timeIntervalSince1970], @"ed" : [self extraParametersWithDate:date].toString } mutableCopy]; if (config.customDimension != nil) {