SwiftUI:什么是@AppStorage 属性包装器 [英] SwiftUI: What is @AppStorage property wrapper

查看:13
本文介绍了SwiftUI:什么是@AppStorage 属性包装器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我曾经使用以下语句将重要的应用程序数据(例如登录凭据)保存到 UserDefaults 中:

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

UserDefaults.standard.set("sample@email.com", forKey: "emailAddress")

现在,我知道 SwiftUI 引入了新的属性包装器,名为:

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

@AppStorage

@AppStorage

谁能解释一下新功能的工作原理?

Could anyone please explain how the new feature works?

推荐答案

AppStorage

@AppStorage 是一种从 UserDefaults 保存和读取变量的便捷方式,并以与 @State 属性相同的方式使用它们.它可以看作是一个 @State 属性,它会自动保存到(并从中读取)UserDefaults.

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.

你可以想到以下几点:

@AppStorage("emailAddress") var emailAddress: String = "sample@email.com"

与此等效(在 SwiftUI 中不允许并且不会编译):

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")
    }
}

请注意,@AppStorage 的行为类似于 @State:对其值的更改将使视图无效并重绘.

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

默认@AppStorage 将使用UserDefaults.standard.但是,您可以指定自己的 UserDefaults 存储:

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

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


不支持的类型(例如,Array):

如 iOSDevil 的 answer 中所述,AppStorage 目前使用有限:


Unsupported types (e.g., Array):

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

您可以在@AppStorage 中使用的类型(目前)仅限于:Bool、Int、Double、String、URL、Data

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

如果你想使用任何其他类型(比如Array),你可以添加对RawRepresentable的一致性:

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
    }
}

演示:

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))
            }
        }
    }
}


有用的链接:

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆