SwiftUI: How to persist @Published variable using UserDefaults?
import SwiftUI
import Combine
fileprivate var cancellables = [String : AnyCancellable] ()
public extension Published {
init(wrappedValue defaultValue: Value, key: String) {
let value = UserDefaults.standard.object(forKey: key) as? Value ?? defaultValue
self.init(initialValue: value)
cancellables[key] = projectedValue.sink { val in
UserDefaults.standard.set(val, forKey: key)
}
}
}
class Settings: ObservableObject {
@Published(key: "isLogedIn") var isLogedIn = false
...
}
Sample: https://youtu.be/TXdAg_YvBNE
Version for all Codable
types check out here
To persist your data you could use the @AppStorage
property wrapper.
However, without using @Published
your ObservableObject
will no longer put out the news about the changed data. To fix this, simply call objectWillChange.send()
from the property's willSet
observer.
import SwiftUI
class Settings: ObservableObject {
@AppStorage("Example") var example: Bool = false {
willSet {
// Call objectWillChange manually since @AppStorage is not published
objectWillChange.send()
}
}
}
It should be possible to compose a new property wrapper:
Composition was left out of the first revision of this proposal, because one can manually compose property wrapper types. For example, the composition @A @B could be implemented as an AB wrapper:
@propertyWrapper
struct AB<Value> {
private var storage: A<B<Value>>
var wrappedValue: Value {
get { storage.wrappedValue.wrappedValue }
set { storage.wrappedValue.wrappedValue = newValue }
}
}
The main benefit of this approach is its predictability: the author of AB decides how to best achieve the composition of A and B, names it appropriately, and provides the right API and documentation of its semantics. On the other hand, having to manually write out each of the compositions is a lot of boilerplate, particularly for a feature whose main selling point is the elimination of boilerplate. It is also unfortunate to have to invent names for each composition---when I try the compose A and B via @A @B, how do I know to go look for the manually-composed property wrapper type AB? Or maybe that should be BA?
Ref: Property WrappersProposal: SE-0258