SwiftUI: What is @AppStorage property wrapper

吃可爱长大的小学妹 提交于 2020-11-24 17:33:47

问题


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

UserDefaults.standard.set("sample@email.com", 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?


回答1:


@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 = "sample@email.com"

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

@State var emailAddress: String = "sample@email.com" {
    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(...)) ...

Useful links:

  • What is the @AppStorage property wrapper?
  • AppStorage Property Wrapper SwiftUI



回答2:


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"




回答3:


This is a persistent storage provided by SwiftUI. This code will persist the email across app launches.

struct AppStorageView: View {
    @AppStorage("emailAddress") var emailAddress = "initial@hey.com"
    var body: some View {
        TextField("Email Address", text: $emailAddress)
    }
}

With pure SwiftUI code, we can now persist such data without using UserDefaults at all.

But if you do want to access the underlying data, it is no secret that the wrapper is using UserDefaults. For example, you can still update using UserDefaults.standard.set(...), and the benefit is that AppStorage observes the store, and the SwiftUI view will update automatically.




回答4:


Re-implementation for iOS 13 and without SwiftUI

In additon to pawello2222 answer, here. is the reimplementation of the AppStorage that I named it as UserDefaultStorage:

@propertyWrapper
struct UserDefaultStorage<T: Codable> {
    private let key: String
    private let defaultValue: T

    private let userDefaults: UserDefaults

    init(key: String, default: T, store: UserDefaults = .standard) {
        self.key = key
        self.defaultValue = `default`
        self.userDefaults = store
    }

    var wrappedValue: T {
        get {
            guard let data = userDefaults.data(forKey: key) else {
                return defaultValue
            }
            let value = try? JSONDecoder().decode(T.self, from: data)
            return value ?? defaultValue
        }
        set {
            let data = try? JSONEncoder().encode(newValue)
            userDefaults.set(data, forKey: key)
        }
    }
}

This wrapper can store/restore any kind of codable into/from the user defaults. Also, it works in iOS 13 and it doesn't need to import SwiftUI.

Usage

@UserDefaultStorage(key: "myCustomKey", default: 0)
var myValue: Int

Note that it can't be used directly as a State



来源:https://stackoverflow.com/questions/62562534/swiftui-what-is-appstorage-property-wrapper

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!