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

Support initial value for optional key #54

Open
sindresorhus opened this issue Oct 24, 2020 · 4 comments
Open

Support initial value for optional key #54

sindresorhus opened this issue Oct 24, 2020 · 4 comments
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@sindresorhus
Copy link
Owner

sindresorhus commented Oct 24, 2020

I have:

extension Defaults.Keys {
	static let refreshInterval = Key<TimeInterval?>("refreshInterval")
}

And I would like to specify an initial value, meaning one that is used before any value is set. This is different from default, which is used whenever the value is nil, which would not work here as it would make it impossible to set the value to nil, which is the whole point of making the value optional.

What I'm thinking:

extension Defaults.Keys {
	static let refreshInterval = Key<TimeInterval?>("refreshInterval", initialValue: 3600)
}

The problem is that there's no good way to differentiate whether a key unset or nil.

  • object(forKey:) returns nil whether it's unset or set to nil.
  • suite.dictionaryRepresentation().keys.contains(key) returns nil whether it's unset or set to nil.
  • suite.persistentDomain(forName:).keys.contains(key) would work, but we only have the suite instance, not the suite name. And the suite instance doesn't expose the suite name...
  • CFPreferencesCopyValue returns the true value ignoring the suite.register defaults, but it requires a suite name.

Possible solutions:

  1. Force passing a suiteName parameter too if you want to use initialValue with a non-standard suite. (and use CFPreferencesCopyValue)
  2. Keep track of keys that are set in an internal UserDefaults entry.
  3. Other ideas?
@sindresorhus sindresorhus added the enhancement New feature or request label Oct 24, 2020
@sindresorhus
Copy link
Owner Author

@hank121314 Any opinions on this?

@hank121314
Copy link
Collaborator

IMO, Although the second solution will be more user friendly, it will create an extra space storage(internal UserDefaults).

I prefer the first one 😄.
So bad we could not retrieve the suite name from suite 😭 .

@sindresorhus
Copy link
Owner Author

Yeah, I agree. The most common use-case is to use the standard suite anyway.

@sindresorhus
Copy link
Owner Author

sindresorhus commented Nov 17, 2022

Seems like CFPreferencesCopyValue does not work either, at least on macOS 13. Maybe it used to work. So it looks like we'll have to manage the state ourselves.

I'm thinking we can store it in a key called __DEFAULTS__keysThatHaveBeenSet. It would be an array of keys that have been set once.

The init would be:

public convenience init<T>(
	_ key: String,
	initialValue: Value,
	suite: UserDefaults = .standard
) where Value == T? {}

We would only store keys coming from this initializer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants