The most "tuple -like" way to handle tuples in preferences:
Saving tuples to prefs is a very common thing.
The nature of tuples is that they are simple, sloppy, untyped, unnamed, fast and light versions of arrays. They're a "shoddy array".
Hence the best idiom and most natural way to save tuples is as a shoddy array.
If the tuple types are all the same and simple, definitely use a shoddy array.
If the tuple types are mixed but easily "saved as" a type, definitely use a shoddy array.
Here's an example of the completely common thing of saving a tuple of "sort column and sort direction", which every app uses constantly.
///For a given screen name save the recent sort col and sense.
func set(forScreen: String, sortColumnSense: (Int, Bool)) {
UserDefaults.standard.set(
[sortColumnSense.0, (sortColumnSense.1 ? 1 : 0)],
forKey: "sortTup_\(forScreen.suffix(64))")
}
///For a given screen name recover the recent sort col sense
func getSortColumnSense(forScreen: String) -> (Int, Bool)? {
let quasi = UserDefaults.standard.array(forKey: "sortTup_\(forScreen.suffix(64))")
guard let quasi,
quasi.count == 2,
let tup = quasi as? [Int]
else { return nil }
return (tup[0], (tup[1] == 0 ? false : true))
}
This completely avoids the complicated issue of consistency & cleanup if you use N different prefs keys, and the simple ad-hoc nature of storing/checking centralizes all the checking logic to SSOT so that it's impossible for any team member to be on a different page and is completely type migration safe, which is otherwise a huge amount of code if you use one of the other three approaches.
synchronize
onNSUserDefaults
is almost never necessary and calling it "just in case" is not recommended by Apple. – Bearish