Skip to content
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

Custom UserDefaults Compatibility #4427

Open
lucamegh opened this issue Oct 30, 2024 · 2 comments
Open

Custom UserDefaults Compatibility #4427

lucamegh opened this issue Oct 30, 2024 · 2 comments

Comments

@lucamegh
Copy link

lucamegh commented Oct 30, 2024

Our app uses a custom UserDefaultsClient interface to manage UserDefaults, defined as follows:

@DependencyClient
public struct UserDefaultsClient: Sendable {
  public var bool: @Sendable (_ forKey: String) -> Bool = { _ in false }

  public var setBool: @Sendable (_ forKey: String) -> Void

  ...
}

The SDK currently lacks support for abstractions like these, causing a compile error when trying to use UserDefaultsClient instead of UserDefaults:

@Dependency(UserDefaultsClient.self) var userDefaults

Purchases.configure(
 with: Configuration
     .builder(withAPIKey: apiKey)
     .with(userDefaults: userDefaults) // Compiler Error!
)

To work around this limitation, I am forced to add a new dependency endpoint that provides direct access to the wrapped UserDefaults instance.

@DependencyClient
public struct UserDefaultsClient: Sendable {
  ...

  public var wrapped: @Sendable () -> UserDefaults
}

However, this workaround defeats the purpose of the abstraction, as it forces us back to using a concrete UserDefaults instance.

Solution

  1. Introduce UserDefaultsProtocol:
    Add a protocol to the SDK that mirrors the UserDefaults methods used within the SDK:
public protocol UserDefaultsProtcol {
  func bool(forKey defaultName: String) -> Bool

  func set(_ value: Bool, forKey defaultName: String)

  ...
}
  1. Extend Configuration.Builder:
    Add support for UserDefaultsProtocol in the Configuration.Builder:
@objc public func with(userDefaults: UserDefaultsProtocol) -> Builder {
  self.userDefaults = userDefaults
  return self
}
  1. Conform UserDefaults (and UserDefaultsClient) to UserDefaultsProtocol.

The solution enables custom UserDefaults implementations, such as UserDefaultsClient, to integrate seamlessly with the SDK, enhancing flexibility without introducing breaking changes to the public API.

@RCGitBot
Copy link
Contributor

👀 We've just linked this issue to our internal tracker and notified the team. Thank you for reporting, we're checking this out!

@nyeu
Copy link
Contributor

nyeu commented Nov 4, 2024

Hi @lucamegh! Thank you for your suggestion - we will look into it and prioritize it accordingly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants