你可以像这样使用简单的属性包装器:
用法
@SettingsBundleStorage(key: "storageUsage_preference")
var storageUsage: Double
注意,只需在变量前添加@objc
,就可以使之与100%的Objective-C兼容。
代码实现:
SettingsBundle
值存储在UserDefaults
中,因此您可以为其使用自定义的PropertyWrapper
。以下包装器将适用于任何UserDefault
值,包括SettingsBundle
的所有值。
属性包装器
@propertyWrapper
public struct SettingsBundleStorage<T> {
private let key: String
public init(key: String) {
self.key = key
setBundleDefaults(plist: .root)
setBundleDefaults(plist: .child(name: "DeveloperOptions"))
}
public var wrappedValue: T {
get { UserDefaults.standard.value(forKey: key) as! T }
set { UserDefaults.standard.set(newValue, forKey: key) }
}
}
根节点和子节点
您需要为根节点和子节点的plist
传递以下枚举:
extension SettingsBundleStorage {
enum PList {
case root
case child(name: String)
var name: String {
var file: String
switch self {
case .root: file = "Root"
case .child(let name): file = name.replacingOccurrences(of: ".plist", with: "")
}
file.append(".plist")
return file
}
}
}
查找并设置默认值。
该包装器使用此函数查找捆绑密钥的默认值:
extension SettingsBundleStorage {
func setBundleDefaults(plist: PList = .root) {
let settingsName = "Settings"
let settingsExtension = "bundle"
let settingsPreferencesItems = "PreferenceSpecifiers"
let settingsPreferenceKey = "Key"
let settingsPreferenceDefaultValue = "DefaultValue"
guard let settingsBundleURL = Bundle.main.url(forResource: settingsName, withExtension: settingsExtension),
let settingsData = try? Data(contentsOf: settingsBundleURL.appendingPathComponent(plist.name)),
let settingsPlist = try? PropertyListSerialization.propertyList(
from: settingsData,
options: [],
format: nil) as? [String: Any],
let settingsPreferences = settingsPlist?[settingsPreferencesItems] as? [[String: Any]] else {
return assertionFailure("Can not get the \(plist.name) from the bundle: \(settingsName)")
}
var defaultsToRegister = [String: Any]()
settingsPreferences.forEach { preference in
if let key = preference[settingsPreferenceKey] as? String {
defaultsToRegister[key] = preference[settingsPreferenceDefaultValue]
}
}
UserDefaults.standard.register(defaults: defaultsToRegister)
}
}
这个包装器可以将任何可编码的内容存储/恢复到用户默认设置中,包括所有已符合可编码协议的 Swift 标准数据类型。
另外,您可以找到一种相似但代码更少的方式来访问任何用户默认设置中的键值,您可以查看这里的答案。
[[NSUserDefaults standardUserDefaults] synchronize];
应该也要添加吗? - Zigii Wong