-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add dict preference model #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,85 @@ | ||
| import Foundation | ||
|
|
||
| /// | ||
| /// `PreferenceGetter` is a protocol that defines an interface for retrieving various types of values from a preference store. | ||
| /// | ||
| /// This protocol provides a standardized way to access stored preferences regardless of the underlying storage mechanism. | ||
| /// Each method follows a consistent pattern of accepting a string key and returning an optional value of the specified type. | ||
| /// The optional return type reflects the possibility that the requested key might not exist in the preference store. | ||
| /// | ||
| /// ## Supported Value Types | ||
| /// - `Bool`: Boolean values | ||
| /// - `Int`: Integer values | ||
| /// - `Double`: Double-precision floating point values | ||
| /// - `Data`: Binary data | ||
| /// - `[String: Any]`: Dictionary values (commonly used for storing complex objects) | ||
| /// | ||
| /// ## Usage Example | ||
| /// ```swift | ||
| /// let preferences: PreferenceGetter = UserDefaultPreferenceGetterAdapter() | ||
| /// | ||
| /// // Retrieve a boolean preference | ||
| /// if let isEnabled = preferences.getBool("feature.enabled") { | ||
| /// print("Feature is enabled: \(isEnabled)") | ||
| /// } else { | ||
| /// print("Feature enabled setting not found") | ||
| /// } | ||
| /// | ||
| /// // Retrieve user settings as a dictionary | ||
| /// if let settings = preferences.getDict("user.settings") { | ||
| /// print("User has \(settings.count) settings configured") | ||
| /// } | ||
| /// ``` | ||
| /// | ||
| /// ## Implementation Notes | ||
| /// When implementing this protocol, consider the following: | ||
| /// - Methods should return `nil` when a key doesn't exist | ||
| /// - Type conversion should be handled safely (return `nil` rather than crashing on type mismatch) | ||
| /// - Consider thread safety for concurrent access scenarios | ||
| /// | ||
| public protocol PreferenceGetter { | ||
| /// | ||
| /// Retrieves a Boolean value associated with the specified key. | ||
| /// | ||
| /// - Parameter key: The key to look up in the preference store. | ||
| /// - Returns: The Boolean value associated with the specified key, or `nil` if the key | ||
| /// doesn't exist or the value is not a Boolean. | ||
| /// | ||
| func getBool(_ key: String) -> Bool? | ||
|
|
||
| /// | ||
| /// Retrieves an integer value associated with the specified key. | ||
| /// | ||
| /// - Parameter key: The key to look up in the preference store. | ||
| /// - Returns: The integer value associated with the specified key, or `nil` if the key | ||
| /// doesn't exist or the value is not an integer. | ||
| /// | ||
| func getInt(_ key: String) -> Int? | ||
|
|
||
| /// | ||
| /// Retrieves a double-precision floating-point value associated with the specified key. | ||
| /// | ||
| /// - Parameter key: The key to look up in the preference store. | ||
| /// - Returns: The Double value associated with the specified key, or `nil` if the key | ||
| /// doesn't exist or the value is not a Double. | ||
| /// | ||
| func getDouble(_ key: String) -> Double? | ||
|
|
||
| /// | ||
| /// Retrieves binary data associated with the specified key. | ||
| /// | ||
| /// - Parameter key: The key to look up in the preference store. | ||
| /// - Returns: The Data value associated with the specified key, or `nil` if the key | ||
| /// doesn't exist or the value is not Data. | ||
| /// | ||
| func getData(_ key: String) -> Data? | ||
|
|
||
| /// | ||
| /// Retrieves a dictionary associated with the specified key. | ||
| /// | ||
| /// - Parameter key: The key to look up in the preference store. | ||
| /// - Returns: The dictionary associated with the specified key, or `nil` if the key | ||
| /// doesn't exist or the value is not a dictionary. | ||
| /// | ||
| func getDict(_ key: String) -> [String: Any]? | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,84 @@ | ||
| import Foundation | ||
|
|
||
| /// | ||
| /// `PreferenceSetter` is a protocol that defines an interface for storing various types of values in a preference store. | ||
| /// | ||
| /// This protocol provides a standardized way to save preferences regardless of the underlying storage mechanism. | ||
| /// Each method follows a consistent pattern of accepting a string key and a value of the specified type. | ||
| /// The setter methods handle the serialization and storage of the values in the backing store. | ||
| /// | ||
| /// ## Supported Value Types | ||
| /// - `Bool`: Boolean values | ||
| /// - `Int`: Integer values | ||
| /// - `Double`: Double-precision floating point values | ||
| /// - `Data`: Binary data | ||
| /// - `[String: Any]`: Dictionary values (commonly used for storing complex objects) | ||
| /// | ||
| /// ## Usage Example | ||
| /// ```swift | ||
| /// let preferences: PreferenceSetter = UserDefaultPreferenceSetterAdapter() | ||
| /// | ||
| /// // Store a boolean preference | ||
| /// preferences.setBool("feature.enabled", value: true) | ||
| /// | ||
| /// // Store user settings as a dictionary | ||
| /// let settings: [String: Any] = ["theme": "dark", "fontSize": 14, "notifications": true] | ||
| /// preferences.setDict("user.settings", value: settings) | ||
| /// ``` | ||
| /// | ||
| /// ## Implementation Notes | ||
| /// When implementing this protocol, consider the following: | ||
| /// - Ensure values are properly persisted to the underlying storage | ||
| /// - Handle type serialization appropriately for the storage medium | ||
| /// - Consider thread safety for concurrent write operations | ||
| /// - Implement proper error handling within the implementation | ||
| /// - Consider implementing synchronization behavior if needed (e.g., immediate write to disk) | ||
| /// | ||
| public protocol PreferenceSetter { | ||
| /// | ||
| /// Stores a Boolean value in the preference store for the specified key. | ||
| /// | ||
| /// - Parameters: | ||
| /// - key: The key under which to store the value. | ||
| /// - value: The Boolean value to store. | ||
| /// | ||
| func setBool(_ key: String, value: Bool) | ||
|
|
||
| /// | ||
| /// Stores an integer value in the preference store for the specified key. | ||
| /// | ||
| /// - Parameters: | ||
| /// - key: The key under which to store the value. | ||
| /// - value: The integer value to store. | ||
| /// | ||
| func setInt(_ key: String, value: Int) | ||
|
|
||
| /// | ||
| /// Stores a double-precision floating-point value in the preference store for the specified key. | ||
| /// | ||
| /// - Parameters: | ||
| /// - key: The key under which to store the value. | ||
| /// - value: The Double value to store. | ||
| /// | ||
| func setDouble(_ key: String, value: Double) | ||
|
|
||
| /// | ||
| /// Stores binary data in the preference store for the specified key. | ||
| /// | ||
| /// - Parameters: | ||
| /// - key: The key under which to store the value. | ||
| /// - value: The Data object to store. | ||
| /// | ||
| func setData(_ key: String, value: Data) | ||
|
|
||
| /// | ||
| /// Stores a dictionary in the preference store for the specified key. | ||
| /// | ||
| /// - Parameters: | ||
| /// - key: The key under which to store the value. | ||
| /// - value: The dictionary to store. | ||
| /// - Note: The dictionary must contain only property list compatible types | ||
| /// if using implementations like UserDefaults. | ||
| /// | ||
| func setDict(_ key: String, value: [String: Any]) | ||
| } |
111 changes: 111 additions & 0 deletions
111
Sources/EasyUserDefaultPreference/PreferenceGetterProvider.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,29 +1,140 @@ | ||
| import Foundation | ||
|
|
||
| /// `PreferenceGetterProvider` is a protocol that defines an abstraction for retrieving raw values from a preference store. | ||
| /// | ||
| /// This protocol is designed to decouple the retrieval logic from the underlying storage mechanism, enabling flexibility | ||
| /// and testability. It serves as the foundation for adapters like `UserDefaultPreferenceGetterAdapter` that implement | ||
| /// higher-level interfaces such as `PreferenceGetter`. | ||
| /// | ||
| /// ## Purpose | ||
| /// The primary purpose of `PreferenceGetterProvider` is to provide a low-level interface for fetching values | ||
| /// from a storage system (e.g., `UserDefaults`) without imposing type constraints. The retrieved values are | ||
| /// typically cast to the desired type by higher-level abstractions. | ||
| /// | ||
| /// ## Usage Example | ||
| /// ```swift | ||
| /// // Example of a custom provider | ||
| /// struct CustomPreferenceGetterProvider: PreferenceGetterProvider { | ||
| /// private var storage: [String: Any] = [:] | ||
| /// | ||
| /// func value(forKey key: String) -> Any? { | ||
| /// return storage[key] | ||
| /// } | ||
| /// } | ||
| /// | ||
| /// let provider = CustomPreferenceGetterProvider() | ||
| /// let value = provider.value(forKey: "example.key") | ||
| /// ``` | ||
| /// | ||
| /// ## Implementation Notes | ||
| /// - The `value(forKey:)` method should return `nil` if the key does not exist in the storage. | ||
| /// - The returned value is expected to be cast to the appropriate type by the caller. | ||
| /// - Implementations should ensure thread safety if the underlying storage is accessed concurrently. | ||
| public protocol PreferenceGetterProvider { | ||
| /// Retrieves a raw value associated with the specified key from the preference store. | ||
| /// | ||
| /// - Parameter key: The key to look up in the preference store. | ||
| /// - Returns: The raw value associated with the key, or `nil` if the key does not exist. | ||
| func value(forKey key: String) -> Any? | ||
| } | ||
|
|
||
| /// | ||
| /// `UserDefaultPreferenceGetterAdapter` is a concrete implementation of the `PreferenceGetter` protocol | ||
| /// that retrieves values from the `UserDefaults` system. | ||
| /// | ||
| /// This adapter uses a `PreferenceGetterProvider` to abstract the underlying storage mechanism, | ||
| /// allowing for flexibility and testability. By default, it uses `UserDefaults.standard` as the provider. | ||
| /// | ||
| /// ## Purpose | ||
| /// The adapter provides a seamless way to access stored preferences in `UserDefaults` while adhering to the | ||
| /// `PreferenceGetter` protocol. It ensures type safety and handles type casting for various data types. | ||
| /// | ||
| /// ## Supported Value Types | ||
| /// - `Bool`: Boolean values | ||
| /// - `Int`: Integer values | ||
| /// - `Double`: Double-precision floating point values | ||
| /// - `Data`: Binary data | ||
| /// - `[String: Any]`: Dictionary values | ||
| /// | ||
| /// ## Usage Example | ||
| /// ```swift | ||
| /// let getter = UserDefaultPreferenceGetterAdapter() | ||
| /// | ||
| /// // Retrieve a boolean value | ||
| /// if let isEnabled = getter.getBool("feature.enabled") { | ||
| /// print("Feature is enabled: \(isEnabled)") | ||
| /// } | ||
| /// | ||
| /// // Retrieve a dictionary value | ||
| /// if let settings = getter.getDict("user.settings") { | ||
| /// print("User settings: \(settings)") | ||
| /// } | ||
| /// ``` | ||
| /// | ||
| /// ## Implementation Notes | ||
| /// - The `provider` is responsible for fetching raw values from the underlying storage. | ||
| /// - Type casting is performed to ensure the returned value matches the expected type. | ||
| /// - If the key does not exist or the value cannot be cast to the expected type, the methods return `nil`. | ||
| /// | ||
| public struct UserDefaultPreferenceGetterAdapter: PreferenceGetter { | ||
| private let provider: PreferenceGetterProvider | ||
|
|
||
| /// | ||
| /// Initializes the adapter with a `PreferenceGetterProvider`. | ||
| /// | ||
| /// - Parameter provider: The provider responsible for fetching raw values. Defaults to `UserDefaults.standard`. | ||
| /// | ||
| public init(provider: PreferenceGetterProvider = UserDefaults.standard) { | ||
| self.provider = provider | ||
| } | ||
|
|
||
| /// | ||
| /// Retrieves a Boolean value associated with the specified key. | ||
| /// | ||
| /// - Parameter key: The key to look up in the preference store. | ||
| /// - Returns: The Boolean value associated with the key, or `nil` if the key does not exist or the value is not a Boolean. | ||
| /// | ||
| public func getBool(_ key: String) -> Bool? { | ||
| provider.value(forKey: key) as? Bool | ||
| } | ||
|
|
||
| /// | ||
| /// Retrieves an integer value associated with the specified key. | ||
| /// | ||
| /// - Parameter key: The key to look up in the preference store. | ||
| /// - Returns: The integer value associated with the key, or `nil` if the key does not exist or the value is not an integer. | ||
| /// | ||
| public func getInt(_ key: String) -> Int? { | ||
| provider.value(forKey: key) as? Int | ||
| } | ||
|
|
||
| /// | ||
| /// Retrieves a double-precision floating-point value associated with the specified key. | ||
| /// | ||
| /// - Parameter key: The key to look up in the preference store. | ||
| /// - Returns: The Double value associated with the key, or `nil` if the key does not exist or the value is not a Double. | ||
| /// | ||
| public func getDouble(_ key: String) -> Double? { | ||
| provider.value(forKey: key) as? Double | ||
| } | ||
|
|
||
| /// | ||
| /// Retrieves binary data associated with the specified key. | ||
| /// | ||
| /// - Parameter key: The key to look up in the preference store. | ||
| /// - Returns: The Data value associated with the key, or `nil` if the key does not exist or the value is not Data. | ||
| /// | ||
| public func getData(_ key: String) -> Data? { | ||
| provider.value(forKey: key) as? Data | ||
| } | ||
|
|
||
| /// | ||
| /// Retrieves a dictionary associated with the specified key. | ||
| /// | ||
| /// - Parameter key: The key to look up in the preference store. | ||
| /// - Returns: The dictionary associated with the key, or `nil` if the key does not exist or the value is not a dictionary. | ||
| /// | ||
| public func getDict(_ key: String) -> [String : Any]? { | ||
| provider.value(forKey: key) as? [String: Any] | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pinning dependencies to the
mainbranch can introduce instability. Consider using a version-based requirement to ensure reproducible builds.