diff --git a/Analytics/Classes/Integrations/SEGIntegrationsManager.m b/Analytics/Classes/Integrations/SEGIntegrationsManager.m index 0d3518166..613554c0c 100644 --- a/Analytics/Classes/Integrations/SEGIntegrationsManager.m +++ b/Analytics/Classes/Integrations/SEGIntegrationsManager.m @@ -423,6 +423,12 @@ - (void)refreshSettings NSDictionary *previouslyCachedSettings = [self cachedSettings]; if (previouslyCachedSettings && [previouslyCachedSettings count] > 0) { [self setCachedSettings:previouslyCachedSettings]; + } else if (self.configuration.defaultSettings != nil) { + // If settings request fail, load a user-supplied version if present. + // but make sure segment.io is in the integrations + NSMutableDictionary *newSettings = [self.configuration.defaultSettings serializableMutableDeepCopy]; + newSettings[@"integrations"][@"Segment.io"][@"apiKey"] = self.configuration.writeKey; + [self setCachedSettings:newSettings]; } else { // If settings request fail, fall back to using just Segment integration. // Doesn't address situations where this callback never gets called (though we don't expect that to ever happen). diff --git a/Analytics/Classes/Internal/SEGAnalyticsUtils.h b/Analytics/Classes/Internal/SEGAnalyticsUtils.h index 6214a9a3a..98dca482e 100644 --- a/Analytics/Classes/Internal/SEGAnalyticsUtils.h +++ b/Analytics/Classes/Internal/SEGAnalyticsUtils.h @@ -36,6 +36,7 @@ NSString *SEGEventNameForScreenTitle(NSString *title); // Deep copy and check NSCoding conformance @protocol SEGSerializableDeepCopy +-(id _Nullable) serializableMutableDeepCopy; -(id _Nullable) serializableDeepCopy; @end diff --git a/Analytics/Classes/Internal/SEGAnalyticsUtils.m b/Analytics/Classes/Internal/SEGAnalyticsUtils.m index f82cd9ddf..0b268fc45 100644 --- a/Analytics/Classes/Internal/SEGAnalyticsUtils.m +++ b/Analytics/Classes/Internal/SEGAnalyticsUtils.m @@ -244,9 +244,9 @@ static id SEGCoerceJSONObject(id obj) @implementation NSDictionary(SerializableDeepCopy) -- (NSDictionary *)serializableDeepCopy +- (id)serializableDeepCopy:(BOOL)mutable { - NSMutableDictionary *returnDict = [[NSMutableDictionary alloc] initWithCapacity:self.count]; + NSMutableDictionary *result = [[NSMutableDictionary alloc] initWithCapacity:self.count]; NSArray *keys = [self allKeys]; for (id key in keys) { id aValue = [self objectForKey:key]; @@ -263,17 +263,29 @@ - (NSDictionary *)serializableDeepCopy } if ([aValue conformsToProtocol:@protocol(SEGSerializableDeepCopy)]) { - theCopy = [aValue serializableDeepCopy]; + theCopy = [aValue serializableDeepCopy:mutable]; } else if ([aValue conformsToProtocol:@protocol(NSCopying)]) { theCopy = [aValue copy]; } else { theCopy = aValue; } - [returnDict setValue:theCopy forKey:key]; - } + [result setValue:theCopy forKey:key]; + } - return [returnDict copy]; + if (mutable) { + return result; + } else { + return [result copy]; + } +} + +- (NSDictionary *)serializableDeepCopy { + return [self serializableDeepCopy:NO]; +} + +- (NSMutableDictionary *)serializableMutableDeepCopy { + return [self serializableDeepCopy:YES]; } @end @@ -281,9 +293,9 @@ - (NSDictionary *)serializableDeepCopy @implementation NSArray(SerializableDeepCopy) --(NSArray *)serializableDeepCopy +-(id)serializableDeepCopy:(BOOL)mutable { - NSMutableArray *returnArray = [[NSMutableArray alloc] initWithCapacity:self.count]; + NSMutableArray *result = [[NSMutableArray alloc] initWithCapacity:self.count]; for (id aValue in self) { id theCopy = nil; @@ -299,16 +311,30 @@ -(NSArray *)serializableDeepCopy } if ([aValue conformsToProtocol:@protocol(SEGSerializableDeepCopy)]) { - theCopy = [aValue serializableDeepCopy]; + theCopy = [aValue serializableDeepCopy:mutable]; } else if ([aValue conformsToProtocol:@protocol(NSCopying)]) { theCopy = [aValue copy]; } else { theCopy = aValue; } - [returnArray addObject:theCopy]; + [result addObject:theCopy]; } - return [returnArray copy]; + if (mutable) { + return result; + } else { + return [result copy]; + } +} + + +- (NSArray *)serializableDeepCopy { + return [self serializableDeepCopy:NO]; } +- (NSMutableArray *)serializableMutableDeepCopy { + return [self serializableDeepCopy:YES]; +} + + @end diff --git a/Analytics/Classes/SEGAnalyticsConfiguration.h b/Analytics/Classes/SEGAnalyticsConfiguration.h index 22400ab86..1d5611735 100644 --- a/Analytics/Classes/SEGAnalyticsConfiguration.h +++ b/Analytics/Classes/SEGAnalyticsConfiguration.h @@ -127,6 +127,13 @@ typedef NSMutableURLRequest *_Nonnull (^SEGRequestFactory)(NSURL *_Nonnull); */ @property (nonatomic, strong, nullable) id crypto; + +/** + * Set the default settings to use if Segment.com cannot be reached. + * An example configuration can be found here, using your write key: https://cdn-settings.segment.com/v1/projects/YOUR_WRITE_KEY/settings + */ +@property (nonatomic, strong, nullable) NSDictionary *defaultSettings; + /** * Set custom middlewares. Will be run before all integrations */