首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SwiftUI:@AppStorage包装器是什么

SwiftUI:@AppStorage包装器是什么
EN

Stack Overflow用户
提问于 2020-06-24 19:17:28
回答 7查看 13.9K关注 0票数 34

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

代码语言:javascript
复制
UserDefaults.standard.set("sample@email.com", forKey: "emailAddress")

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

@AppStorage

有人能解释一下这个新功能是如何工作的吗?

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2020-06-24 20:42:51

AppStorage

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

你可以想到以下几点:

代码语言:javascript
复制
@AppStorage("emailAddress") var emailAddress: String = "sample@email.com"

与此等价(在SwiftUI中是不允许的,也不会编译):

代码语言:javascript
复制
@State var emailAddress: String = "sample@email.com" {
    get {
        UserDefaults.standard.string(forKey: "emailAddress")
    }
    set {
        UserDefaults.standard.set(newValue, forKey: "emailAddress")
    }
}

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

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

代码语言:javascript
复制
@AppStorage("emailAddress", store: UserDefaults(...)) ...

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

正如iOSDevil的回答中所提到的,AppStorage目前用途有限:

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

如果您想使用任何其他类型(如Array),则可以向RawRepresentable添加一致性

代码语言:javascript
复制
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
    }
}

演示:

代码语言:javascript
复制
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))
            }
        }
    }
}

有用的链接:

票数 50
EN

Stack Overflow用户

发布于 2020-07-11 12:41:56

免责声明: iOS 14 Beta 2

除了其他有用的答案之外,您可以在@AppStorage中使用的类型(目前)仅限于: Bool、Int、Double、String、URL、Data

尝试使用其他类型(如Array)会导致错误:“调用初始化程序时没有完全匹配”

票数 8
EN

Stack Overflow用户

发布于 2020-10-31 07:56:23

iOS 13和不带SwiftUI的重新实现

除了pawello2222的答案,这里。是我命名为AppStorage的UserDefaultStorage的重新实现。

代码语言:javascript
复制
@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)
        }
    }
}

此包装器可以将(任何类型的可编码)存储/还原到/从用户默认值中恢复。而且,它在iOS 13中工作,而且不需要导入SwiftUI

用法

代码语言:javascript
复制
@UserDefaultStorage(key: "myCustomKey", default: 0)
var myValue: Int

注意到不能直接用作State

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62562534

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档