Greetings, traveler!
SwiftUI has a fancy property wrapper for reading values from UserDefaults. It’s pretty convenient because it automatically updates your view’s body property whenever the value in UserDefaults changes. Basically, it keeps an eye on a specific key in UserDefaults and refreshes your UI if that key changes. By default, @AppStorage monitors UserDefaults.standard, but if you wish, you can instruct it to keep a watch on a specific app group instead.
Let’s look at an example of usage:
struct ContentView: View {
@AppStorage("animal") var animal: String = "Dog"
var body: some View {
Button("Cat") {
animal = "cat"
}
}
}
We have updated the value in UserDefaults to ‘Cat’ by clicking on the button. Let’s write some code in the old way to get a better idea of how it would work.
UserDefaults.standard.set("Cat", forKey: "animal")
To switch the group which the @AppStore will monitor for any changes, you just need to use the following code.
@AppStorage("animal", store: UserDefaults(suiteName: "group.com.livsycode.appstorageexample")) var username: String = "Dog"
You can improve the convenience of this code for future reuse.
public extension UserDefaults {
static let sharedInstance = UserDefaults(suiteName: "group.com.livsycode.appstorageexample")!
}
// Usage
@AppStorage("animal", store: UserDefaults.sharedInstance) var animal = "Cat"
@AppStorage with different data types
Although the @AppStorage property wrapper is quite useful, it only supports the following data types: Bool, Int, Double, String, URL, and Data. UserDefaults, on the other hand, supports more types. In addition to the data types we have already discussed, @AppStorage can also handle data types that follow the RawRepresentable protocol and have a RawValue of either Int or String. This means that we can now access data types that were previously not supported by @AppStorage in UserDefaults. Overall, it’s a pretty neat feature!
Let’s look at an example with the ‘Date’ type:
extension Date: RawRepresentable {
public typealias RawValue = String
public init?(rawValue: RawValue) {
guard let data = rawValue.data(using: .utf8),
let date = try? JSONDecoder().decode(Date.self, from: data) else {
return nil
}
self = date
}
public var rawValue: RawValue{
guard let data = try? JSONEncoder().encode(self),
let result = String(data: data, encoding: .utf8) else {
return ""
}
return result
}
}
// Usage
@AppStorage("date") var date = Date()
If we use an enum, its ‘RawValue’ must be an Int or String.
enum Option: Int {
case a, b, c
}
// Usage
@AppStorage("option") var option = Option.a
Conclusion
Today, we found a new cool tool to work with data in SwiftUI. In our next article, we’ll check out how we can use @AppStorege to change the color scheme of our app. So, see you there!
Check out other posts:
- How to change the order of Calendar weekdaySymbols
- Mutex in Swift 6 and Synchronization
- Exploring the take() method for Optionals
- How to display an icon with a title using the Label in SwiftUI
- How to dysplay byte counts in Swift
- How to format date in SwiftUI
- How to use Hierarchical Colors in SwiftUI
- Global actors and Singletons
- How to organize layout with ControlGroup in SwiftUI