Skip to content

Commit 846bef6

Browse files
Alda/new init api behavior (#194)
* Renamed the simplified APIs. * Cleaned up the init method API calls in the demo app. * Removed async and sync init APIs and moved the functionality to existing init methods. Also updated the logs. * Updated logs for the new init APIs. * Updated the demo app with the new init methods (i.e., remove the async and sync methods). * Consolidated and cleaned up client initialization tests. * Redefined how we get the bundled datafile. We are going to use the datafile from the manager builder instead of looking for a specific file name in the app resources. This solution is more clean and is applicable to fullstack SDKs as well.
1 parent f027ede commit 846bef6

File tree

6 files changed

+243
-427
lines changed

6 files changed

+243
-427
lines changed

OptimizelyDemoApp/AppDelegate.swift

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
8888
}
8989
}
9090
}
91-
91+
9292
defaultNotificationCenter.addObserver(forName: NSNotification.Name("OptimizelyEventTracked"), object: nil, queue: nil) { (note) in
9393
print("Received a tracking notification: \n", note)
9494
if let userInfo : Dictionary<String, AnyObject> = note.userInfo as! Dictionary<String, AnyObject>? {
@@ -121,7 +121,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
121121

122122
// ---- Create the Datafile Manager ----
123123
let datafileManager = OPTLYDatafileManagerDefault.init{(builder) in
124-
// builder!.datafileFetchInterval = TimeInterval(self.datafileManagerDownloadInterval)
124+
// builder!.datafileFetchInterval = TimeInterval(self.datafileManagerDownloadInterval)
125125
builder!.projectId = self.projectId
126126
}
127127

@@ -134,25 +134,14 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
134134

135135
// After creating the client, there are three different ways to intialize the manager:
136136

137-
// --- 1. Synchronous Initialization with fallback ----
138-
// let optimizelyClient = optimizelyManager?.initializeSync(projectId)
139-
// let variation = optimizelyClient?.activate(self.experimentKey, userId:self.userId, attributes: self.attributes)
140-
// self.setRootViewController(optimizelyClient: optimizelyClient, bucketedVariation:variation)
141-
142-
// --- 2. Asynchronous Initialization with fallback ----
143-
optimizelyManager?.initializeAsync(projectId, callback: { [weak self] (error, optimizelyClient) in
144-
let variation = optimizelyClient?.activate((self?.experimentKey)!, userId:(self?.userId)!, attributes:(self?.attributes))
137+
// ---- 1. Asynchronous Initialization -----
138+
// initialize Optimizely Client from a datafile download
139+
optimizelyManager?.initialize(callback: { [weak self] (error, optimizelyClient) in
140+
let variation = optimizelyClient?.activate((self?.experimentKey)!, userId: (self?.userId)!, attributes: (self?.attributes))
145141
self?.setRootViewController(optimizelyClient: optimizelyClient, bucketedVariation:variation)
146142
})
147143

148-
// ---- 3. Asynchronous Initialization -----
149-
// initialize Optimizely Client from a datafile download
150-
// optimizelyManager?.initialize(callback: { [weak self] (error, optimizelyClient) in
151-
// let variation = optimizelyClient?.activate((self?.experimentKey)!, userId: (self?.userId)!, attributes: (self?.attributes))
152-
// self?.setRootViewController(optimizelyClient: optimizelyClient, bucketedVariation:variation)
153-
// })
154-
155-
// ---- 4. Synchronous Initialization with Datafile ----
144+
// ---- 2. Synchronous Initialization with Datafile ----
156145
// load the datafile from the app bundle
157146
// let bundle = Bundle.init(for: self.classForCoder)
158147
// let filePath = bundle.path(forResource: datafileName, ofType: "json")
@@ -169,7 +158,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
169158
// let variation = optimizelyClient?.activate(self.experimentKey, userId:self.userId, attributes: self.attributes)
170159
// self.setRootViewController(optimizelyClient: optimizelyClient, bucketedVariation:variation)
171160

172-
// --- 5. Synchronous Initialization with Saved Datafile ----
161+
// --- 3. Synchronous Initialization with Saved Datafile ----
173162
// let optimizelyClient = optimizelyManager?.initialize()
174163
// let variation = optimizelyClient?.activate(self.experimentKey, userId:self.userId, attributes: self.attributes)
175164
// self.setRootViewController(optimizelyClient: optimizelyClient, bucketedVariation:variation)

OptimizelySDKCore/OptimizelySDKCore/OPTLYLoggerMessages.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,10 +160,10 @@ extern NSString *const OPTLYLoggerMessagesManagerEventDispatcherDoesNotConformTo
160160
extern NSString *const OPTLYLoggerMessagesManagerLoggerDoesNotConformToOPTLYLoggerProtocol;
161161
extern NSString *const OPTLYLoggerMessagesManagerMustBeInitializedWithProjectId;
162162
extern NSString *const OPTLYLoggerMessagesManagerProjectIdCannotBeEmptyString;
163-
extern NSString *const OPTLYLoggerMessagesManagerSyncInit;
164-
extern NSString *const OPTLYLoggerMessagesManagerAsyncInit;
165-
extern NSString *const OPTLYLoggerMessagesManagerAsyncInitErrorDatafileDownload;
166-
extern NSString *const OPTLYLoggerMessagesManagerAsyncInitNoDatafileUpdates;
163+
extern NSString *const OPTLYLoggerMessagesManagerInit;
164+
extern NSString *const OPTLYLoggerMessagesManagerInitWithCallback;
165+
extern NSString *const OPTLYLoggerMessagesManagerInitWithCallbackErrorDatafileDownload;
166+
extern NSString *const OPTLYLoggerMessagesManagerInitWithCallbackNoDatafileUpdates;
167167
extern NSString *const OPTLYLoggerMessagesManagerAttemptingBundleDataLoad;
168168
extern NSString *const OPTLYLoggerMessagesManagerBundleDataLoadError;
169169
extern NSString *const OPTLYLoggerMessagesManagerBundledDataLoaded;

OptimizelySDKCore/OptimizelySDKCore/OPTLYLoggerMessages.m

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -154,10 +154,10 @@
154154
NSString *const OPTLYLoggerMessagesManagerLoggerDoesNotConformToOPTLYLoggerProtocol = @"[MANAGER] Logger does not conform to the OPTLYLogger protocol.";
155155
NSString *const OPTLYLoggerMessagesManagerMustBeInitializedWithProjectId = @"[MANAGER] An Optimizely Manager instance must be initialized with a project ID.";
156156
NSString *const OPTLYLoggerMessagesManagerProjectIdCannotBeEmptyString = @"[MANAGER] The project ID for the Optimizely Manager instance cannot be an empty string";
157-
NSString *const OPTLYLoggerMessagesManagerSyncInit = @"[MANAGER] Synchronously initializing client with project ID %@.";
158-
NSString *const OPTLYLoggerMessagesManagerAsyncInit = @"[MANAGER] Asynchronously initializing client with project ID %@.";
159-
NSString *const OPTLYLoggerMessagesManagerAsyncInitErrorDatafileDownload = @"[MANAGER] Error downloading datafile: %@.";
160-
NSString *const OPTLYLoggerMessagesManagerAsyncInitNoDatafileUpdates = @"[MANAGER] Not downloading new datafile — no updates have been made.";
157+
NSString *const OPTLYLoggerMessagesManagerInit = @"[MANAGER] Initializing client for project %@.";
158+
NSString *const OPTLYLoggerMessagesManagerInitWithCallback = @"[MANAGER] Initializing client with callback for project %@.";
159+
NSString *const OPTLYLoggerMessagesManagerInitWithCallbackErrorDatafileDownload = @"[MANAGER] Error downloading datafile: %@.";
160+
NSString *const OPTLYLoggerMessagesManagerInitWithCallbackNoDatafileUpdates = @"[MANAGER] Not downloading new datafile — no updates have been made.";
161161
NSString *const OPTLYLoggerMessagesManagerAttemptingBundleDataLoad = @"[MANAGER] Attempting to load the bundled datafile.";
162162
NSString *const OPTLYLoggerMessagesManagerBundleDataLoadError = @"[MANAGER] Unabled to load the bundled datafile because of the following error: %@";
163163
NSString *const OPTLYLoggerMessagesManagerBundledDataLoaded = @"[MANAGER] The bundled datafile %@ was loaded.";

OptimizelySDKShared/OptimizelySDKShared/OPTLYManagerBase.h

Lines changed: 23 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -70,63 +70,50 @@ typedef void (^OPTLYManagerBuilderBlock)(OPTLYManagerBuilder * _Nullable builder
7070
/// iOS App Version
7171
@property (nonatomic, readonly, strong, nonnull) NSString *appVersion;
7272

73-
/*
74-
* Synchronous call that would retrieve the datafile from local cache. If it fails to load from local cache it will return a dummy instance
75-
*/
76-
- (nullable OPTLYClient *)initialize;
77-
78-
/**
79-
* Synchronous call that would instantiate the client from the datafile given
80-
* If the datafile is bad, then the client will try to get the datafile from local cache (if it exists). If it fails to load from local cache it will return a dummy instance
81-
*/
82-
- (nullable OPTLYClient *)initializeWithDatafile:(nonnull NSData *)datafile;
83-
84-
85-
/**
86-
* Asynchronously gets the client from a datafile downloaded from the CDN.
87-
* If the client could not be initialized, the error will be set in the callback.
88-
*/
89-
- (void)initializeWithCallback:(void(^ _Nullable)(NSError * _Nullable error, OPTLYClient * _Nullable client))callback;
9073

9174
/**
9275
* Synchronously initializes the client using the latest
93-
* cached datafile with a bundled datafile as fallback.
94-
*
95-
* If the cached datafile fails to load, the bundled datafile is used.
76+
* cached datafile with a fallback of the bundled datafile
77+
* (i.e., the datafile provided in the OPTLYManagerBuilder
78+
* during the manager initialization).
9679
*
97-
* In order for the bundled datafile to be properly loaded, the
98-
* name should follow this format: optimizely_<projectID>.json
80+
* If the cached datafile fails to load, the bundled datafile
81+
* is used.
9982
*
100-
* @param projectId The ID of the project you want
101-
* to initialize your client with.
10283
*/
103-
- (nullable OPTLYClient *)initializeSync:(nonnull NSString *)projectId;
84+
- (nullable OPTLYClient *)initialize;
10485

10586
/**
10687
* Asynchronously initializes the client using the latest
107-
* downloaded datafile with a bundled datafile as fallback.
88+
* downloaded datafile with a fallback of the bundled datafile
89+
* (i.e., the datafile provided in the OPTLYManagerBuilder
90+
* during the manager initialization).
10891
*
10992
* In the case that there is an error in the datafile download,
11093
* the latest cached datafile (if one exists) is used.
11194
*
11295
* If there are no updates in the datafile, then the datafile is not
11396
* downloaded and the latest cached datafile is used.
11497
*
115-
* If the cached datafile fails to load, then the bundled datafile
116-
* is used.
117-
*
118-
* In order for the bundled datafile to be properly loaded, the
119-
* name should follow this format: optimizely_<projectID>.json
98+
* If the cached datafile fails to load, then the datafile provided
99+
* in the manager builder is used.
120100
*
121-
* @param projectId The ID of the project you want
122-
* to initialize your client with.
123101
* @param callback The block called following the initialization
124102
* of the client.
125103
*/
126-
- (void)initializeAsync:(nonnull NSString *)projectId
127-
callback:(void(^ _Nullable)(NSError * _Nullable error,
128-
OPTLYClient * _Nullable client))callback;
104+
- (void)initializeWithCallback:(void(^ _Nullable)(NSError * _Nullable error,
105+
OPTLYClient * _Nullable client))callback;
129106

107+
/**
108+
* Synchronously instantiates the client from the provided datafile.
109+
* If the datafile is invalid, then the client will attempt to retrieve
110+
* the cached datafile. If getting the datafile from cache fails,
111+
* then a dummy client instance will be returned (i.e., all method calls on the client
112+
* will be NoOps).
113+
*
114+
* @param datafile The datafile used to instantiate the client.
115+
*/
116+
- (nullable OPTLYClient *)initializeWithDatafile:(nonnull NSData *)datafile;
130117

131118
/*
132119
* Gets the cached Optimizely client.

OptimizelySDKShared/OptimizelySDKShared/OPTLYManagerBase.m

Lines changed: 45 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,24 @@ - (instancetype)init {
9696
#pragma mark - Client Getters
9797

9898
- (OPTLYClient *)initialize {
99-
// the datafile could have been set in the builder (this should take precedence over the saved datafile)
100-
if (!self.datafile) {
101-
self.datafile = [self.datafileManager getSavedDatafile:nil];
99+
[self.logger logMessage:[NSString stringWithFormat:OPTLYLoggerMessagesManagerInit, self.projectId]
100+
withLevel:OptimizelyLogLevelInfo];
101+
102+
NSData *data = nil;
103+
104+
// get the cached datafile if the builder does not contain a datafile
105+
if (data == nil) {
106+
data = [self.datafileManager getSavedDatafile:nil];
102107
}
103-
self.optimizelyClient = [self initializeClientWithManagerSettingsAndDatafile:self.datafile];
104-
return self.optimizelyClient;
108+
109+
// fall back to the datafile provided by the manager builder if we can't get the saved datafile
110+
if (data == nil) {
111+
data = self.datafile;
112+
}
113+
114+
OPTLYClient *client = [self initializeWithDatafile:data];
115+
116+
return client;
105117
}
106118

107119
- (OPTLYClient *)initializeWithDatafile:(NSData *)datafile {
@@ -110,17 +122,34 @@ - (OPTLYClient *)initializeWithDatafile:(NSData *)datafile {
110122
}
111123

112124
- (void)initializeWithCallback:(void (^)(NSError * _Nullable, OPTLYClient * _Nullable))callback {
113-
[self.datafileManager downloadDatafile:self.projectId
114-
completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
115-
if ([(NSHTTPURLResponse *)response statusCode] == 304) {
116-
data = [self.datafileManager getSavedDatafile:&error];
117-
}
118-
self.optimizelyClient = [self initializeClientWithManagerSettingsAndDatafile:data];
119-
120-
if (callback) {
121-
callback(error, self.optimizelyClient);
122-
}
123-
}];
125+
[self.logger logMessage:[NSString stringWithFormat:OPTLYLoggerMessagesManagerInitWithCallback, self.projectId]
126+
withLevel:OptimizelyLogLevelInfo];
127+
128+
[self.datafileManager downloadDatafile:self.projectId completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
129+
if (error) {
130+
[self.logger logMessage:[NSString stringWithFormat:OPTLYLoggerMessagesManagerInitWithCallbackErrorDatafileDownload, error.localizedDescription]
131+
withLevel:OptimizelyLogLevelError];
132+
data = [self.datafileManager getSavedDatafile:&error];
133+
} else {
134+
// 304 response code means there is not datafile updates
135+
if ([(NSHTTPURLResponse *)response statusCode] == 304) {
136+
[self.logger logMessage:OPTLYLoggerMessagesManagerInitWithCallbackNoDatafileUpdates
137+
withLevel:OptimizelyLogLevelError];
138+
data = [self.datafileManager getSavedDatafile:&error];
139+
}
140+
}
141+
142+
// fall back to the datafile provided by the manager builder if we can't get the saved datafile
143+
if (data == nil) {
144+
data = self.datafile;
145+
}
146+
147+
OPTLYClient *client = [self initializeWithDatafile:data];
148+
149+
if (callback) {
150+
callback(error, client);
151+
}
152+
}];
124153
}
125154

126155
- (OPTLYClient *)getOptimizely {
@@ -148,79 +177,8 @@ - (OPTLYClient *)initializeClientWithManagerSettingsAndDatafile:(NSData *)datafi
148177
return client;
149178
}
150179

151-
- (nullable OPTLYClient *)initializeSync:(nonnull NSString *)projectId
152-
{
153-
[self.logger logMessage:[NSString stringWithFormat:OPTLYLoggerMessagesManagerSyncInit, projectId]
154-
withLevel:OptimizelyLogLevelInfo];
155-
156-
NSData *data = [self.datafileManager getSavedDatafile:nil];
157-
158-
// fall back to the bundled datafile if we can't get the saved datafile
159-
if (data == nil) {
160-
data = [self loadBundleDatafile:projectId error:nil];
161-
}
162-
163-
OPTLYClient *client = [self initializeWithDatafile:data];
164-
165-
return client;
166-
}
167-
168-
- (void)initializeAsync:(nonnull NSString *)projectId
169-
callback:(void(^ _Nullable)(NSError * _Nullable error, OPTLYClient * _Nullable client))callback
170-
{
171-
[self.logger logMessage:[NSString stringWithFormat:OPTLYLoggerMessagesManagerAsyncInit, projectId]
172-
withLevel:OptimizelyLogLevelInfo];
173-
174-
[self.datafileManager downloadDatafile:projectId completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
175-
if (error) {
176-
[self.logger logMessage:[NSString stringWithFormat:OPTLYLoggerMessagesManagerAsyncInitErrorDatafileDownload, error.localizedDescription]
177-
withLevel:OptimizelyLogLevelError];
178-
data = [self.datafileManager getSavedDatafile:&error];
179-
} else {
180-
// 304 response code means there is not datafile updates
181-
if ([(NSHTTPURLResponse *)response statusCode] == 304) {
182-
[self.logger logMessage:OPTLYLoggerMessagesManagerAsyncInitNoDatafileUpdates
183-
withLevel:OptimizelyLogLevelError];
184-
data = [self.datafileManager getSavedDatafile:&error];
185-
}
186-
}
187-
188-
// fall back to the bundled datafile if we can't get the saved datafile
189-
if (data == nil) {
190-
data = [self loadBundleDatafile:projectId error:&error];
191-
}
192-
193-
OPTLYClient *client = [self initializeWithDatafile:data];
194-
195-
if (callback) {
196-
callback(error, client);
197-
}
198-
}];
199-
}
200-
201180
#pragma mark - Helper Methods
202181

203-
- (NSData *)loadBundleDatafile:(NSString *)projectId error:(NSError * __autoreleasing *)error {
204-
205-
[self.logger logMessage:OPTLYLoggerMessagesManagerAttemptingBundleDataLoad
206-
withLevel:OptimizelyLogLevelInfo];
207-
208-
NSString *datafileName = [NSString stringWithFormat:@"%@_%@", OptimizelyBundleDatafilePrefix, projectId];
209-
NSString *filePath = [[NSBundle bundleForClass:[self class]] pathForResource:datafileName ofType:OptimizelyBundleDatafileFileTypeExtension];
210-
NSString *fileContents =[NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:error];
211-
212-
if (error && *error) {
213-
NSError *fileError = (NSError *)*error;
214-
NSString *errorDescription = fileError.localizedDescription;
215-
[self.logger logMessage:[NSString stringWithFormat:OPTLYLoggerMessagesManagerBundleDataLoadError, errorDescription] withLevel:OptimizelyLogLevelError];
216-
} else {
217-
[self.logger logMessage:[NSString stringWithFormat:OPTLYLoggerMessagesManagerBundledDataLoaded, datafileName] withLevel:OptimizelyLogLevelInfo];
218-
}
219-
220-
NSData *jsonData = [fileContents dataUsingEncoding:NSUTF8StringEncoding];
221-
return jsonData;
222-
}
223-
224182
- (NSString *)description {
225183
return [NSString stringWithFormat:@"projectId: %@ \nclientEngine: %@\nclientVersion: %@\ndatafile:%@\nlogger:%@\nerrorHandler:%@\ndatafileManager:%@\neventDispatcher:%@\nuserProfile:%@", self.projectId, self.clientEngine, self.clientVersion, self.datafile, self.logger, self.errorHandler, self.datafileManager, self.eventDispatcher, self.userProfileService];
226184
}

0 commit comments

Comments
 (0)