您可以像这样使用简单的属性包装器:
用法
@SettingsBundleStorage(key: "storageUsage_preference")
var storageUsage: Double
请注意,@objc
只需在变量之前添加即可 100% 兼容 Objective-c 。
这背后的代码实现:
设置捆绑包值是实时的,UserDefaults
因此您可以PropertyWrapper
为其使用自定义。以下包装器适用于任何UserDefault
值,包括SettingsBundle
.
属性包装器
@propertyWrapper
public struct SettingsBundleStorage<T> {
private let key: String
public init(key: String) {
self.key = key
setBundleDefaults(plist: .root) // This is the main plist
setBundleDefaults(plist: .child(name: "DeveloperOptions")) // This is an example child.
}
public var wrappedValue: T {
get { UserDefaults.standard.value(forKey: key) as! T }
set { UserDefaults.standard.set(newValue, forKey: key) }
}
}
根和孩子
plist
您应该为 root 和 child s传递以下枚举:
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 标准数据类型。
此外,您可以找到一个类似但代码版本更少的用于从任何用户默认访问任何键值的代码版本,您可以在此处查看此答案