Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CassiusPacheco/bf3fdc9e27b189d9b2c858caa65a3b67 to your computer and use it in GitHub Desktop.
Save CassiusPacheco/bf3fdc9e27b189d9b2c858caa65a3b67 to your computer and use it in GitHub Desktop.
Testable @UserDefaults property wrapper
import Foundation
public protocol UserDefaultsInterface {
func set(_ value: Any?, forKey defaultName: String)
func object(forKey defaultName: String) -> Any?
}
extension UserDefaults: UserDefaultsInterface {}
class UserDefaultsMock: UserDefaultsInterface {
var valueSet: Any?
var valueSetKey: String?
var objectKey: String?
var objectToBeReturned: Any?
func set(_ value: Any?, forKey defaultName: String) {
valueSet = value
valueSetKey = defaultName
}
func object(forKey defaultName: String) -> Any? {
objectKey = defaultName
return objectToBeReturned
}
}
enum UserDefaultsKeys: String {
case userSeenPopUp = "user_seen_popup"
}
@propertyWrapper
struct Preferences<T> {
var defaults: UserDefaultsInterface = UserDefaults.standard
let key: UserDefaultsKeys
let defaultValue: T
var wrappedValue: T {
get {
defaults.object(forKey: key.rawValue) as? T ?? defaultValue
} set {
defaults.set(newValue, forKey: key.rawValue)
}
}
init(wrappedValue: T, key: UserDefaultsKeys) {
defaultValue = wrappedValue
self.key = key
}
}
class SomeClass {
@Preferences(key: .userSeenPopUp)
var hasUserSeenPopUp = false
init(defaults: UserDefaultsInterface = UserDefaults.standard) {
_hasUserSeenPopUp.defaults = defaults
}
func showPopUpIfNecessary() {
guard !hasUserSeenPopUp else { return }
// show pop up
hasUserSeenPopUp.toggle()
}
}
let mock = UserDefaultsMock()
let test = SomeClass(defaults: mock) // Inject mocked instance into the property wrapper
assert(!test.hasUserSeenPopUp)
test.showPopUpIfNecessary()
assert(mock.valueSet as? Bool == true)
assert(mock.valueSetKey == UserDefaultsKeys.userSeenPopUp.rawValue)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment