diff --git a/Sources/Customization/DefaultEventDispatcher.swift b/Sources/Customization/DefaultEventDispatcher.swift index 2852d259a..c7b95388e 100644 --- a/Sources/Customization/DefaultEventDispatcher.swift +++ b/Sources/Customization/DefaultEventDispatcher.swift @@ -17,7 +17,7 @@ import Foundation public enum DataStoreType { - case file, memory, userDefaults + case file(directory: FileManager.SearchPathDirectory? = nil), memory, userDefaults } open class DefaultEventDispatcher: BackgroundingCallbacks, OPTEventDispatcher { @@ -54,7 +54,7 @@ open class DefaultEventDispatcher: BackgroundingCallbacks, OPTEventDispatcher { let reachability = NetworkReachability(maxContiguousFails: 1) public init(batchSize: Int = DefaultValues.batchSize, - backingStore: DataStoreType = .file, + backingStore: DataStoreType = .file(directory: nil), dataStoreName: String = "OPTEventQueue", timerInterval: TimeInterval = DefaultValues.timeInterval, maxQueueSize: Int = DefaultValues.maxQueueSize) { @@ -63,9 +63,14 @@ open class DefaultEventDispatcher: BackgroundingCallbacks, OPTEventDispatcher { self.maxQueueSize = maxQueueSize >= 100 ? maxQueueSize : DefaultValues.maxQueueSize switch backingStore { - case .file: - self.eventQueue = DataStoreQueueStackImpl(queueStackName: "OPTEventQueue", - dataStore: DataStoreFile<[Data]>(storeName: dataStoreName)) + case .file(let directory): + if let directory { + self.eventQueue = DataStoreQueueStackImpl(queueStackName: "OPTEventQueue", + dataStore: DataStoreFile<[Data]>(storeName: dataStoreName, directory: directory)) + } else { + self.eventQueue = DataStoreQueueStackImpl(queueStackName: "OPTEventQueue", + dataStore: DataStoreFile<[Data]>(storeName: dataStoreName)) + } case .memory: self.eventQueue = DataStoreQueueStackImpl(queueStackName: "OPTEventQueue", dataStore: DataStoreMemory<[Data]>(storeName: dataStoreName)) diff --git a/Sources/Implementation/Datastore/DataStoreFile.swift b/Sources/Implementation/Datastore/DataStoreFile.swift index 2ad28c628..51c92e310 100644 --- a/Sources/Implementation/Datastore/DataStoreFile.swift +++ b/Sources/Implementation/Datastore/DataStoreFile.swift @@ -30,21 +30,27 @@ open class DataStoreFile: OPTDataStore where T: Codable { return threadSafeLogger.logger } - public init(storeName: String, async: Bool = true) { - self.async = async - dataStoreName = storeName - lock = DispatchQueue(label: storeName) + public convenience init(storeName: String, async: Bool = true) { #if os(tvOS) || os(macOS) let directory = FileManager.SearchPathDirectory.cachesDirectory #else let directory = FileManager.SearchPathDirectory.documentDirectory #endif + + self.init(storeName: storeName, directory: directory, async: async) + } + + public init(storeName: String, directory: FileManager.SearchPathDirectory, async: Bool = true) { + self.async = async + + dataStoreName = storeName + lock = DispatchQueue(label: storeName) + if let url = FileManager.default.urls(for: directory, in: .userDomainMask).first { self.url = url.appendingPathComponent(storeName, isDirectory: false) } else { self.url = URL(fileURLWithPath: storeName) } - } func isArray() -> Bool { diff --git a/Tests/OptimizelyTests-Common/DataStoreTests.swift b/Tests/OptimizelyTests-Common/DataStoreTests.swift index 05003b7d2..ec58c44cf 100644 --- a/Tests/OptimizelyTests-Common/DataStoreTests.swift +++ b/Tests/OptimizelyTests-Common/DataStoreTests.swift @@ -17,10 +17,9 @@ import XCTest class DataStoreTests: XCTestCase { - - override func setUp() { - // Put setup code here. This method is called before the invocation of each test method in the class. - if let url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first { + + private func createDirectoryIfNeeded(directory: FileManager.SearchPathDirectory) { + if let url = FileManager.default.urls(for: directory, in: .userDomainMask).first { if (!FileManager.default.fileExists(atPath: url.path)) { do { try FileManager.default.createDirectory(at: url, withIntermediateDirectories: false, attributes: nil) @@ -30,7 +29,11 @@ class DataStoreTests: XCTestCase { } } + } + override func setUp() { + // Put setup code here. This method is called before the invocation of each test method in the class. + createDirectoryIfNeeded(directory: .documentDirectory) } override func tearDown() { @@ -168,6 +171,19 @@ class DataStoreTests: XCTestCase { datastore.removeItem(forKey: key) } + func testFileStoreCustomDirectory() throws { + createDirectoryIfNeeded(directory: .applicationSupportDirectory) + + let datastore = DataStoreFile<[String]>(storeName: "testFileStore") + + datastore.saveItem(forKey: "testString", value: ["value"]) + let vj = datastore.getItem(forKey: "testString") as! [String] + XCTAssertEqual(vj.first, "value") + + var url = try XCTUnwrap(FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first) + .appendingPathComponent("testFileStore", isDirectory: false) + XCTAssertTrue(FileManager.default.fileExists(atPath: url.path())) + } func testUserDefaults() {