如何解决尝试在 UserDefaults 中观察字符串,但遇到编译错误 更新
我在 GitHub 上有 a small project。
在 TopViewModel.swift 中,我首先获取对象的 JSON 列表,然后将它们存储在 Core Data 中,最后将它们显示在 SwiftUI List
中。
这很好用,但现在我在顶部添加了一个 Picker
,允许用户选择其中一种语言:“en”、“de”、“ru”,然后将字符串存储在 { {1}}:
这也很好用,这对我作为 Swift 新手来说还不错:-)
然而,当我试图从我的视图模型观察 UserDefaults 中的 @AppStorage
键时,我的问题开始了:
我尝试将以下代码添加到 TopViewModel.swift,但它甚至无法编译:
language
编译错误之一是我的视图模型不是 init() {
UserDefaults.standard.addobserver(self,forKeyPath: "language",options: NSkeyvalueObservingOptions.new,context: nil)
}
deinit() {
UserDefaults.standard.removeObserver(self,forKeyPath: "language")
}
func observeValue(forKeyPath keyPath: String?,of object: Any?,change: [NSkeyvalueChangeKey : Any]?,context: UnsafeMutableRawPointer?) {
// How to get language here from the params?
updatetopEntities(language: language)
fetchTopModels(language: language)
}
无法将“Topviewmodel”类型的值转换为预期的参数类型“NSObject”
为什么不呢?
更新:
我已将 NSObject
作为父项添加到 [Topviewmodel.swift],现在当用户选择语言 NSObject
中的值时调用回调方法 observeValue
:>
Picker
剩下的唯一(我认为是次要的)问题是我不知道如何从 class Topviewmodel: NSObject,ObservableObject {
override init() {
super.init()
UserDefaults.standard.addobserver(self,context: nil)
let language = UserDefaults.standard.string(forKey: "language") ?? "en"
updatetopEntities(language: language)
fetchTopModels(language: language)
}
deinit {
UserDefaults.standard.removeObserver(self,forKeyPath: "language")
}
override func observeValue(forKeyPath keyPath: String?,context: UnsafeMutableRawPointer?) {
guard keyPath == "language" else { return }
guard change?.count == 2 else { return }
print("observeValue language=\(change["new"].value)")
// How to get language here from the params?
//updatetopEntities(language: language)
//fetchTopModels(language: language)
}
参数中获取 language
字符串(调用 observeValue
作为解决方法有效,但我有兴趣从参数中提取值,因为调试器在那里显示 UserDefaults.standard.string(forKey: "language")
字符串):
解决方法
你可以试试这个。
extension UserDefaults {
@objc dynamic var language: String {
get { self.string(forKey: "language") ?? "en" }
set { self.setValue(newValue,forKey: "language") }
}
}
class MyObject {
var observer: NSKeyValueObservation?
init() {
observer = UserDefaults.standard.observe(\.language,options: [.new],changeHandler: { (defaults,change) in
// your change logic here
})
}
deinit {
observer?.invalidate()
}
}
更新
import Foundation
extension UserDefaults {
@objc dynamic var language: String {
get { self.string(forKey: #function) ?? "en" }
set { self.setValue(newValue,forKey: #function) }
}
}
class TopViewModel: NSObject {
let defaults = UserDefaults.standard
let languageKeyPath = #keyPath(UserDefaults.language)
override init() {
super.init()
defaults.addObserver(self,forKeyPath: languageKeyPath,options: .new,context: nil)
let language = defaults.language
print("initialLanguage: \(language)")
defaults.language = "en"
defaults.language = "fr"
}
deinit {
defaults.removeObserver(self,forKeyPath: languageKeyPath)
}
override func observeValue(forKeyPath keyPath: String?,of object: Any?,change: [NSKeyValueChangeKey: Any]?,context: UnsafeMutableRawPointer?) {
guard (object as? UserDefaults) === defaults,keyPath == languageKeyPath,let change = change
else { return }
if let updatedLanguage = change[.newKey] as? String {
print("updatedLanguage : \(updatedLanguage)")
}
}
}
// Test code,run init to observe changes
let viewModel = TopViewModel()
,
这里是我自己的解决方案,我必须添加 NSObject
作为父类并使用 change[.newKey]
访问 observeValue
回调方法中的新值:
class TopViewModel: NSObject,ObservableObject {
override init() {
super.init()
UserDefaults.standard.addObserver(self,forKeyPath: "language",options: NSKeyValueObservingOptions.new,context: nil)
let language = UserDefaults.standard.string(forKey: "language") ?? "en"
// use the language string value here
}
deinit {
UserDefaults.standard.removeObserver(self,forKeyPath: "language")
}
override func observeValue(forKeyPath keyPath: String?,change: [NSKeyValueChangeKey : Any]?,context: UnsafeMutableRawPointer?) {
guard keyPath == "language",let change = change,let language = change[.newKey] as? String else {
return
}
// use the language string value here
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。