diff --git a/Sources/XXMessengerClient/Utils/Stored.swift b/Sources/XXMessengerClient/Utils/Stored.swift index 052d638705c6dce4a619fbe18d0d55cf2159733c..ab0de7e1db138d121b2f4a9228f6bb61900d84c4 100644 --- a/Sources/XXMessengerClient/Utils/Stored.swift +++ b/Sources/XXMessengerClient/Utils/Stored.swift @@ -1,3 +1,4 @@ +import Foundation import XCTestDynamicOverlay public struct Stored<Value> { @@ -31,6 +32,26 @@ private final class Memory<Value> { var value: Value } +extension Stored { + public static func userDefaults<T>( + key: String, + userDefaults: UserDefaults = .standard + ) -> Stored<T?> where T: Codable { + let encoder = JSONEncoder() + let decoder = JSONDecoder() + return Stored<T?>( + get: { + guard let data = userDefaults.data(forKey: key) else { return nil } + return try? decoder.decode(T.self, from: data) + }, + set: { newValue in + let data = try? encoder.encode(newValue) + userDefaults.set(data, forKey: key) + } + ) + } +} + extension Stored { public struct MissingValueError: Error, Equatable { public init(typeDescription: String) { diff --git a/Tests/XXMessengerClientTests/Utils/StoredTests.swift b/Tests/XXMessengerClientTests/Utils/StoredTests.swift index 154f61967627500def1526f2944aeb074792c748..834097ef9e870d7b9e297d3131c246c6a068c48a 100644 --- a/Tests/XXMessengerClientTests/Utils/StoredTests.swift +++ b/Tests/XXMessengerClientTests/Utils/StoredTests.swift @@ -1,8 +1,9 @@ +import CustomDump import XCTest @testable import XXMessengerClient final class StoredTests: XCTestCase { - func testInMemory() throws { + func testInMemory() { let stored: Stored<String?> = .inMemory() XCTAssertNil(stored()) @@ -15,4 +16,35 @@ final class StoredTests: XCTestCase { XCTAssertNil(stored()) } + + func testUserDefaults() { + struct Value: Equatable, Codable { + var id = UUID() + } + + let key = "key" + let userDefaults = UserDefaults(suiteName: "XXMessengerClient_StoredTests")! + userDefaults.removeObject(forKey: key) + let stored: Stored<Value?> = .userDefaults( + key: key, + userDefaults: userDefaults + ) + + XCTAssertNoDifference(stored.get(), nil) + + let value = Value() + stored.set(value) + + XCTAssertNoDifference( + userDefaults.data(forKey: key).map { data in + try? JSONDecoder().decode(Value.self, from: data) + }, + value + ) + XCTAssertNoDifference(stored.get(), value) + + userDefaults.set(nil, forKey: key) + + XCTAssertNoDifference(stored.get(), nil) + } }