Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI: What is @AppStorage property wrapper

I used to save important App data like login credentials into UserDefaults using the following statement:

UserDefaults.standard.set("[email protected]", forKey: "emailAddress") 

Now, I have come to know SwiftUI has introduced new property wrapper called:

@AppStorage

Could anyone please explain how the new feature works?

like image 404
Shawkath Srijon Avatar asked Jun 24 '20 19:06

Shawkath Srijon


People also ask

What is property wrapper SwiftUI?

SwiftUI has two properties wrappers for reading the user's environment: @Environment and @ScaledMetric . @Environment is used to read a wide variety of data such as what trait collection is currently active, whether they are using a 2x or 3x screen, what timezone they are on, and more.

What does the @state property wrapper do?

@State. The @State property wrapper is used inside of View objects and allows your view to respond to any changes made to @State . You use @State for properties that are owned by the view that it's contained in. In other words, a view initializes its @State properties itself.

What is @appstorage in Swift?

A property wrapper type that reflects a value from UserDefaults and invalidates a view on a change in value in that user default.

Why we use @published in SwiftUI?

@Published is one of the property wrappers in SwiftUI that allows us to trigger a view redraw whenever changes occur. You can use the wrapper combined with the ObservableObject protocol, but you can also use it within regular classes.


2 Answers

AppStorage

@AppStorage is a convenient way to save and read variables from UserDefaults and use them in the same way as @State properties. It can be seen as a @State property which is automatically saved to (and read from) UserDefaults.

You can think of the following:

@AppStorage("emailAddress") var emailAddress: String = "[email protected]" 

as an equivalent of this (which is not allowed in SwiftUI and will not compile):

@State var emailAddress: String = "[email protected]" {     get {         UserDefaults.standard.string(forKey: "emailAddress")     }     set {         UserDefaults.standard.set(newValue, forKey: "emailAddress")     } } 

Note that @AppStorage behaves like a @State: a change to its value will invalidate and redraw a View.

By default @AppStorage will use UserDefaults.standard. However, you can specify your own UserDefaults store:

@AppStorage("emailAddress", store: UserDefaults(...)) ... 

Unsupported types (e.g., Array):

As mentioned in iOSDevil's answer, AppStorage is currently of limited use:

types you can use in @AppStorage are (currently) limited to: Bool, Int, Double, String, URL, Data

If you want to use any other type (like Array), you can add conformance to RawRepresentable:

extension Array: RawRepresentable where Element: Codable {     public init?(rawValue: String) {         guard let data = rawValue.data(using: .utf8),               let result = try? JSONDecoder().decode([Element].self, from: data)         else {             return nil         }         self = result     }      public var rawValue: String {         guard let data = try? JSONEncoder().encode(self),               let result = String(data: data, encoding: .utf8)         else {             return "[]"         }         return result     } } 

Demo:

struct ContentView: View {     @AppStorage("itemsInt") var itemsInt = [1, 2, 3]     @AppStorage("itemsBool") var itemsBool = [true, false, true]      var body: some View {         VStack {             Text("itemsInt: \(String(describing: itemsInt))")             Text("itemsBool: \(String(describing: itemsBool))")             Button("Add item") {                 itemsInt.append(Int.random(in: 1...10))                 itemsBool.append(Int.random(in: 1...10).isMultiple(of: 2))             }         }     } } 

Useful links:

  • What is the @AppStorage property wrapper?
  • AppStorage Property Wrapper SwiftUI
like image 162
pawello2222 Avatar answered Sep 28 '22 10:09

pawello2222


Disclaimer: iOS 14 Beta 2

In addition to the other useful answers, the types you can use in @AppStorage are (currently) limited to: Bool, Int, Double, String, URL, Data

Attempting to use other types (such as Array) results in the error: "No exact matches in call to initializer"

like image 30
iOSDevil Avatar answered Sep 28 '22 11:09

iOSDevil