diff --git a/Sources/ComposableArchitecture/SharedState/PersistenceKey/AppStorageKey.swift b/Sources/ComposableArchitecture/SharedState/PersistenceKey/AppStorageKey.swift index 5c78f16861c1..e97547d39e06 100644 --- a/Sources/ComposableArchitecture/SharedState/PersistenceKey/AppStorageKey.swift +++ b/Sources/ComposableArchitecture/SharedState/PersistenceKey/AppStorageKey.swift @@ -47,6 +47,15 @@ extension PersistenceReaderKey { AppStorageKey(key) } + /// Creates a persistence key that can read and write to a Date user default. + /// + /// - Parameter key: The key to read and write the value to in the user defaults store. + /// - Returns: A user defaults persistence key. + public static func appStorage(_ key: String) -> Self + where Self == AppStorageKey { + AppStorageKey(key) + } + /// Creates a persistence key that can read and write to a user default as data. /// /// - Parameter key: The key to read and write the value to in the user defaults store. @@ -121,6 +130,15 @@ extension PersistenceReaderKey { AppStorageKey(key) } + /// Creates a persistence key that can read and write to an optional Date user default. + /// + /// - Parameter key: The key to read and write the value to in the user defaults store. + /// - Returns: A user defaults persistence key. + public static func appStorage(_ key: String) -> Self + where Self == AppStorageKey { + AppStorageKey(key) + } + /// Creates a persistence key that can read and write to a user default as optional data. /// /// - Parameter key: The key to read and write the value to in the user defaults store. @@ -198,6 +216,13 @@ public struct AppStorageKey: Sendable { self.store = UncheckedSendable(store) } + fileprivate init(_ key: String) where Value == Date { + @Dependency(\.defaultAppStorage) var store + self.lookup = CastableLookup() + self.key = key + self.store = UncheckedSendable(store) + } + fileprivate init(_ key: String) where Value == Data { @Dependency(\.defaultAppStorage) var store self.lookup = CastableLookup() @@ -254,6 +279,13 @@ public struct AppStorageKey: Sendable { self.store = UncheckedSendable(store) } + fileprivate init(_ key: String) where Value == Date? { + @Dependency(\.defaultAppStorage) var store + self.lookup = OptionalLookup(base: CastableLookup()) + self.key = key + self.store = UncheckedSendable(store) + } + fileprivate init(_ key: String) where Value == Data? { @Dependency(\.defaultAppStorage) var store self.lookup = OptionalLookup(base: CastableLookup()) diff --git a/Tests/ComposableArchitectureTests/AppStorageTests.swift b/Tests/ComposableArchitectureTests/AppStorageTests.swift index 0cd414a91e22..2bc2ef3ce67a 100644 --- a/Tests/ComposableArchitectureTests/AppStorageTests.swift +++ b/Tests/ComposableArchitectureTests/AppStorageTests.swift @@ -51,6 +51,38 @@ final class AppStorageTests: XCTestCase { XCTAssertEqual(defaults.url(forKey: "url"), URL(string: "https://example.com")) } + func testDefaultsReadDate() { + let expectedDate = Date() + @Dependency(\.defaultAppStorage) var defaults + defaults.set(expectedDate, forKey: "date") + @Shared(.appStorage("date")) var date: Date? + XCTAssertEqual(date, expectedDate) + } + + func testDefaultsRegistered_Date() { + let expectedDate = Date() + @Dependency(\.defaultAppStorage) var defaults + @Shared(.appStorage("date")) var date: Date = expectedDate + XCTAssertEqual(defaults.object(forKey: "date") as? Date, expectedDate) + + let newDate = Date().addingTimeInterval(60) + date = newDate + XCTAssertEqual(date, newDate) + XCTAssertEqual(defaults.object(forKey: "date") as? Date, newDate) + } + + func testDefaultsRegistered_Optional_Date() { + let initialDate: Date? = Date() + @Dependency(\.defaultAppStorage) var defaults + @Shared(.appStorage("date")) var date: Date? = initialDate + XCTAssertEqual(defaults.object(forKey: "date") as? Date, initialDate) + + let newDate = Date().addingTimeInterval(60) + date = newDate + XCTAssertEqual(date, newDate) + XCTAssertEqual(defaults.object(forKey: "date") as? Date, newDate) + } + func testDefaultsRegistered_Optional() { @Dependency(\.defaultAppStorage) var defaults @Shared(.appStorage("data")) var data: Data? @@ -184,6 +216,13 @@ final class AppStorageTests: XCTestCase { XCTAssertEqual(url2, nil) } + func testOptionalInitializers_Date() { + @Shared(.appStorage("date1")) var date1: Date? + XCTAssertEqual(date1, nil) + @Shared(.appStorage("date2")) var date2: Date? = nil + XCTAssertEqual(date2, nil) + } + func testRemoveDuplicates() { @Dependency(\.defaultAppStorage) var store @Shared(.appStorage("count")) var count = 0