Skip to content

Commit bacba1a

Browse files
nmarkovic04rubikzube
authored andcommitted
Implemented session incrementing (#61)
* Implemented session incrementing * Comment fixes; Moved session persistence keys to Constants * Fixed an issue when initial track session event wouldn't fire because of an uninitialized delegate * Fixed tests to use NoSessionLoader * Minor changes
1 parent 2c3b0fd commit bacba1a

File tree

15 files changed

+214
-39
lines changed

15 files changed

+214
-39
lines changed

AutocompleteClient.xcodeproj/project.pbxproj

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,10 @@
142142
F6D2E9CC20E21022007F8761 /* CIOTrackSearchResultsLoadedData.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6D2E9CB20E21022007F8761 /* CIOTrackSearchResultsLoadedData.swift */; };
143143
F6DF7B9420849E8D00A7CDAD /* CIOTrackSearchResultClickData.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6DF7B9320849E8D00A7CDAD /* CIOTrackSearchResultClickData.swift */; };
144144
F6EC29AB2175161300DCFA07 /* ClosureSessionManagerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6EC29AA2175161300DCFA07 /* ClosureSessionManagerDelegate.swift */; };
145+
F6EC29AD2175EF1700DCFA07 /* Session.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6EC29AC2175EF1700DCFA07 /* Session.swift */; };
146+
F6EC29AF2176014C00DCFA07 /* SessionLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6EC29AE2176014C00DCFA07 /* SessionLoader.swift */; };
147+
F6EC29B2217601D700DCFA07 /* CIOSessionLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6EC29B1217601D700DCFA07 /* CIOSessionLoader.swift */; };
148+
F6EC29B421762BD700DCFA07 /* NoSessionLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6EC29B321762BD700DCFA07 /* NoSessionLoader.swift */; };
145149
/* End PBXBuildFile section */
146150

147151
/* Begin PBXContainerItemProxy section */
@@ -330,6 +334,10 @@
330334
F6D2E9CB20E21022007F8761 /* CIOTrackSearchResultsLoadedData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIOTrackSearchResultsLoadedData.swift; sourceTree = "<group>"; };
331335
F6DF7B9320849E8D00A7CDAD /* CIOTrackSearchResultClickData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIOTrackSearchResultClickData.swift; sourceTree = "<group>"; };
332336
F6EC29AA2175161300DCFA07 /* ClosureSessionManagerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClosureSessionManagerDelegate.swift; sourceTree = "<group>"; };
337+
F6EC29AC2175EF1700DCFA07 /* Session.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Session.swift; sourceTree = "<group>"; };
338+
F6EC29AE2176014C00DCFA07 /* SessionLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionLoader.swift; sourceTree = "<group>"; };
339+
F6EC29B1217601D700DCFA07 /* CIOSessionLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIOSessionLoader.swift; sourceTree = "<group>"; };
340+
F6EC29B321762BD700DCFA07 /* NoSessionLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoSessionLoader.swift; sourceTree = "<group>"; };
333341
/* End PBXFileReference section */
334342

335343
/* Begin PBXFrameworksBuildPhase section */
@@ -398,9 +406,8 @@
398406
088F7D25210FA43C005B9FB4 /* CurrentTimeDateProvider.swift */,
399407
088F7D24210FA43C005B9FB4 /* DateProvider.swift */,
400408
);
401-
name = Date;
402-
path = "/Users/rubikzube/Github/constructor.io/constructorio-client-swift/AutocompleteClient/FW/Logic/Session/Date";
403-
sourceTree = "<absolute>";
409+
path = Date;
410+
sourceTree = "<group>";
404411
};
405412
08CCD3ED216675C700C3F234 /* ABTesting */ = {
406413
isa = PBXGroup;
@@ -618,10 +625,12 @@
618625
F62510C62052CC5E0040E3DF /* Session */ = {
619626
isa = PBXGroup;
620627
children = (
628+
F6EC29B0217601C400DCFA07 /* Persistence */,
621629
088F7D23210FA429005B9FB4 /* Date */,
622630
088F7D1B210FA3B4005B9FB4 /* CIOSessionManagerDelegate.swift */,
623631
F62510C72052CC6B0040E3DF /* CIOSessionManager.swift */,
624632
F62510C92052CF240040E3DF /* SessionManager.swift */,
633+
F6EC29AC2175EF1700DCFA07 /* Session.swift */,
625634
);
626635
path = Session;
627636
sourceTree = "<group>";
@@ -632,6 +641,7 @@
632641
F62510D020568F250040E3DF /* SessionManagerTests.swift */,
633642
F62510D2205690670040E3DF /* ClosureDateProvider.swift */,
634643
F6EC29AA2175161300DCFA07 /* ClosureSessionManagerDelegate.swift */,
644+
F6EC29B321762BD700DCFA07 /* NoSessionLoader.swift */,
635645
);
636646
path = Session;
637647
sourceTree = "<group>";
@@ -1162,6 +1172,15 @@
11621172
path = JSON;
11631173
sourceTree = "<group>";
11641174
};
1175+
F6EC29B0217601C400DCFA07 /* Persistence */ = {
1176+
isa = PBXGroup;
1177+
children = (
1178+
F6EC29AE2176014C00DCFA07 /* SessionLoader.swift */,
1179+
F6EC29B1217601D700DCFA07 /* CIOSessionLoader.swift */,
1180+
);
1181+
path = Persistence;
1182+
sourceTree = "<group>";
1183+
};
11651184
/* End PBXGroup section */
11661185

11671186
/* Begin PBXHeadersBuildPhase section */
@@ -1235,9 +1254,9 @@
12351254
isa = PBXNativeTarget;
12361255
buildConfigurationList = F688A4531F56B4B600F169C1 /* Build configuration list for PBXNativeTarget "AutocompleteClient" */;
12371256
buildPhases = (
1257+
F688A43C1F56B4B600F169C1 /* Headers */,
12381258
F688A43A1F56B4B600F169C1 /* Sources */,
12391259
F688A43B1F56B4B600F169C1 /* Frameworks */,
1240-
F688A43C1F56B4B600F169C1 /* Headers */,
12411260
F688A43D1F56B4B600F169C1 /* Resources */,
12421261
);
12431262
buildRules = (
@@ -1455,6 +1474,7 @@
14551474
isa = PBXSourcesBuildPhase;
14561475
buildActionMask = 2147483647;
14571476
files = (
1477+
F6EC29AD2175EF1700DCFA07 /* Session.swift in Sources */,
14581478
F672F6BA20ABE9EC00EA1525 /* CIOTrackConversionData.swift in Sources */,
14591479
F1B17CB21F58E5830015FF62 /* AutocompleteResult.swift in Sources */,
14601480
F65015481F586A42008E50C0 /* UIView+FadeInOut.swift in Sources */,
@@ -1477,6 +1497,7 @@
14771497
F650154E1F58724B008E50C0 /* UIColor+RGB.swift in Sources */,
14781498
F60BEA1A1F571956008F0053 /* CIOAutocompleteDelegate.swift in Sources */,
14791499
F61A6B091F698877007826CA /* CIOGroup.swift in Sources */,
1500+
F6EC29B2217601D700DCFA07 /* CIOSessionLoader.swift in Sources */,
14801501
F6B220EB209C68F8003A5D48 /* CustomSearchBar.swift in Sources */,
14811502
F1F68DDA1F58B6A300B42602 /* CIOAutocompleteResponseParser.swift in Sources */,
14821503
F6852559213D604900A27FAA /* AutocompleteResultCount.swift in Sources */,
@@ -1500,6 +1521,7 @@
15001521
F63808FB1F5D49AF00C3B322 /* TaskResponse.swift in Sources */,
15011522
F685255B21413D4D00A27FAA /* CIORequestData.swift in Sources */,
15021523
F1F68DE31F58B8BB00B42602 /* CIOError.swift in Sources */,
1524+
F6EC29AF2176014C00DCFA07 /* SessionLoader.swift in Sources */,
15031525
088F7D1E210FA3C6005B9FB4 /* CIOTrackInputFocusData.swift in Sources */,
15041526
F62510C82052CC6B0040E3DF /* CIOSessionManager.swift in Sources */,
15051527
F68A73131F56E5FB00FA4D1B /* String+Trim.swift in Sources */,
@@ -1553,6 +1575,7 @@
15531575
F60FE90A1F5C5B9D0037A0AB /* AutocompleteQueryRequestBuilderTests.swift in Sources */,
15541576
F64F46A61F595B980094C697 /* ResponseParserTests.swift in Sources */,
15551577
F64E94DD212D7EC300E50EDE /* ConstructorIOTrackingTests.swift in Sources */,
1578+
F6EC29B421762BD700DCFA07 /* NoSessionLoader.swift in Sources */,
15561579
089399DF2161B92600BFE3D9 /* TrackInputFocusRequestBuilderTests.swift in Sources */,
15571580
089399E32161C67D00BFE3D9 /* TrackSearchResultsLoadedRequestBuilder.swift in Sources */,
15581581
F64F46AD1F5963AF0094C697 /* Bundle+Test.swift in Sources */,

AutocompleteClient/Constants/Constants.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,4 +150,10 @@ struct Constants {
150150

151151
static let performURLRequest: (_ request: URLRequest) -> String = { request in return Logging.format("Performing URL Request \(request)") }
152152
}
153+
154+
struct Session{
155+
static let key = "constructor.io/session"
156+
static let id = "constructor.io/session/id"
157+
static let createdAt = "constructor.io/session/createdAt"
158+
}
153159
}

AutocompleteClient/FW/Logic/Session/CIOSessionManager.swift

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,35 @@
77
//
88

99
import Foundation
10-
10+
1111
public class CIOSessionManager: SessionManager {
1212

1313
public weak var delegate: CIOSessionManagerDelegate?
1414

15-
public var sessionID: Int{
15+
private(set) public var session: Session{
1616
didSet{
17-
self.delegate?.sessionDidChange(from: oldValue, to: self.sessionID)
17+
self.sessionLoader.saveSession(self.session)
18+
self.delegate?.sessionDidChange(from: oldValue.id, to: self.session.id)
1819
}
1920
}
20-
var lastSessionRequest: TimeInterval
2121
let timeout: TimeInterval
2222
let dateProvider: DateProvider
23+
let sessionLoader: SessionLoader
2324

24-
init(dateProvider: DateProvider, timeout: TimeInterval){
25-
self.sessionID = 1
25+
init(dateProvider: DateProvider, timeout: TimeInterval, sessionLoader: SessionLoader = CIOSessionLoader()){
2626
self.dateProvider = dateProvider
2727
self.timeout = timeout
28-
self.lastSessionRequest = self.dateProvider.provideDate().timeIntervalSince1970
28+
29+
self.sessionLoader = sessionLoader
30+
self.session = self.sessionLoader.loadSession() ?? Session(id: 1, createdAt: dateProvider.provideDate().timeIntervalSince1970)
2931

3032
NotificationCenter.default.addObserver(self, selector: #selector(applicationDidEnterForeground(_:)), name: Notification.Name.UIApplicationWillEnterForeground, object: nil)
3133
}
34+
35+
public func setup(){
36+
self.reloadSession()
37+
self.sessionLoader.saveSession(self.session)
38+
}
3239

3340
@objc
3441
public func applicationDidEnterForeground(_ notification: Notification){
@@ -37,32 +44,26 @@ public class CIOSessionManager: SessionManager {
3744

3845
public func getSessionWithIncrement() -> Int{
3946
self.reloadSession()
40-
return self.sessionID
47+
return self.session.id
4148
}
4249

4350
public func getSessionWithoutIncrement() -> Int{
44-
return self.sessionID
51+
return self.session.id
4552
}
4653

4754
func reloadSession(){
4855
if self.shouldIncrementSession(){
4956
self.incrementSession()
5057
}
51-
52-
self.setSessionHasBeenRequested()
53-
}
54-
55-
private func setSessionHasBeenRequested(){
56-
self.lastSessionRequest = self.dateProvider.provideDate().timeIntervalSince1970
5758
}
5859

5960
func shouldIncrementSession() -> Bool{
60-
let diff = (self.dateProvider.provideDate().timeIntervalSince1970 - self.lastSessionRequest)
61+
let diff = (self.dateProvider.provideDate().timeIntervalSince1970 - self.session.createdAt)
6162
return diff >= self.timeout
6263
}
6364

6465
func incrementSession(){
65-
self.sessionID += 1
66+
self.session = Session(id: self.session.id + 1, createdAt: self.dateProvider.provideDate().timeIntervalSince1970)
6667
}
6768

6869
deinit {
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//
2+
// CIOSessionLoader.swift
3+
// AutocompleteClient
4+
//
5+
// Copyright © Constructor.io. All rights reserved.
6+
// http://constructor.io/
7+
//
8+
9+
import Foundation
10+
11+
public struct CIOSessionLoader: SessionLoader{
12+
13+
public func loadSession() -> Session?{
14+
if let data = UserDefaults.standard.object(forKey: Constants.Session.key) as? Data{
15+
return NSKeyedUnarchiver.unarchiveObject(with: data) as? Session
16+
}else{
17+
return nil
18+
}
19+
}
20+
21+
public func saveSession(_ session: Session){
22+
let data = NSKeyedArchiver.archivedData(withRootObject: session)
23+
UserDefaults.standard.set(data, forKey: Constants.Session.key)
24+
}
25+
26+
public func clearSession() {
27+
UserDefaults.standard.removeObject(forKey: Constants.Session.key)
28+
}
29+
30+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//
2+
// SessionLoader.swift
3+
// Constructor.io
4+
//
5+
// Copyright © Constructor.io. All rights reserved.
6+
// http://constructor.io/
7+
//
8+
9+
import Foundation
10+
11+
public protocol SessionLoader{
12+
13+
func loadSession() -> Session?
14+
func saveSession(_ session: Session)
15+
16+
func clearSession()
17+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//
2+
// Session.swift
3+
// Constructor.io
4+
//
5+
// Copyright © Constructor.io. All rights reserved.
6+
// http://constructor.io/
7+
//
8+
9+
import Foundation
10+
11+
public class Session: NSObject, NSCoding{
12+
let id: Int
13+
let createdAt: TimeInterval
14+
15+
public init(id: Int, createdAt: TimeInterval){
16+
self.id = id
17+
self.createdAt = createdAt
18+
}
19+
20+
public required init?(coder aDecoder: NSCoder) {
21+
self.id = aDecoder.decodeInteger(forKey: Constants.Session.id)
22+
self.createdAt = aDecoder.decodeDouble(forKey: Constants.Session.createdAt)
23+
}
24+
25+
public func encode(with aCoder: NSCoder) {
26+
aCoder.encode(self.id, forKey: Constants.Session.id)
27+
aCoder.encode(self.createdAt, forKey: Constants.Session.createdAt)
28+
}
29+
}

AutocompleteClient/FW/Logic/Session/SessionManager.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public protocol SessionManager: class{
1212
var delegate: CIOSessionManagerDelegate? { get set }
1313

1414
func getSessionWithIncrement() -> Int
15-
1615
func getSessionWithoutIncrement() -> Int
16+
17+
func setup()
1718
}

AutocompleteClient/FW/Logic/Worker/ConstructorIO.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public class ConstructorIO: CIOSessionManagerDelegate {
2121
public static var logger: CIOLogger = CIOPrintLogger()
2222

2323
private let networkClient: NetworkClient
24-
private let sessionManager: SessionManager
24+
var sessionManager: SessionManager
2525

2626
public var parser: AbstractResponseParser
2727

@@ -40,7 +40,9 @@ public class ConstructorIO: CIOSessionManagerDelegate {
4040
self.sessionManager = DependencyContainer.sharedInstance.sessionManager()
4141
self.parser = DependencyContainer.sharedInstance.responseParser()
4242
self.networkClient = DependencyContainer.sharedInstance.networkClient()
43+
4344
self.sessionManager.delegate = self
45+
self.sessionManager.setup()
4446
}
4547

4648
/// Get autocomplete suggestions for a query.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//
2+
// NoSessionLoader.swift
3+
// AutocompleteClientTests
4+
//
5+
// Copyright © Constructor.io. All rights reserved.
6+
// http://constructor.io/
7+
//
8+
9+
@testable import ConstructorAutocomplete
10+
11+
class NoSessionLoader: SessionLoader{
12+
func loadSession() -> Session? {
13+
return nil
14+
}
15+
func saveSession(_ session: Session) {}
16+
17+
func clearSession() {}
18+
}

0 commit comments

Comments
 (0)