我曾经使用以下语句将重要的应用程序数据(如登录凭据)保存到UserDefaults中:
UserDefaults.standard.set("sample@email.com", forKey: "emailAddress")现在,我知道SwiftUI引入了新的属性包装器,名为:
@AppStorage
有人能解释一下这个新功能是如何工作的吗?
发布于 2020-06-24 20:42:51
AppStorage
@AppStorage是一种从UserDefaults中保存和读取变量并以与@State属性相同的方式使用它们的方便方法。它可以看作是一个@State属性,它被自动保存到(并从) UserDefaults中读取。
你可以想到以下几点:
@AppStorage("emailAddress") var emailAddress: String = "sample@email.com"与此等价(在SwiftUI中是不允许的,也不会编译):
@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存储:
@AppStorage("emailAddress", store: UserDefaults(...)) ...不支持的类型(例如,Array):
正如iOSDevil的回答中所提到的,AppStorage目前用途有限:
您可以在@AppStorage中使用的类型(当前)仅限于: Bool、Int、Double、String、URL、Data
如果您想使用任何其他类型(如Array),则可以向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))
}
}
}
}有用的链接:
发布于 2020-07-11 12:41:56
免责声明: iOS 14 Beta 2
除了其他有用的答案之外,您可以在@AppStorage中使用的类型(目前)仅限于: Bool、Int、Double、String、URL、Data
尝试使用其他类型(如Array)会导致错误:“调用初始化程序时没有完全匹配”
发布于 2020-10-31 07:56:23
iOS 13和不带SwiftUI的重新实现
除了pawello2222的答案,这里。是我命名为AppStorage的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)
}
}
}此包装器可以将(任何类型的可编码)存储/还原到/从用户默认值中恢复。而且,它在iOS 13中工作,而且不需要导入SwiftUI。
用法
@UserDefaultStorage(key: "myCustomKey", default: 0)
var myValue: Int注意到不能直接用作State
https://stackoverflow.com/questions/62562534
复制相似问题