Swift 如何使自定义属性包装可以绑定,可能是使用@State?
我已经创建了一个自定义属性包装器,它作为文件的setter和getter从文件中进行写入和读取Swift 如何使自定义属性包装可以绑定,可能是使用@State?,swift,properties,swiftui,state,property-wrapper,Swift,Properties,Swiftui,State,Property Wrapper,我已经创建了一个自定义属性包装器,它作为文件的setter和getter从文件中进行写入和读取 @propertyWrapper结构说明符{ 让键:字符串 让defaultValue:Value 让plistPath:String var prefs:NSDictionary{ NSDictionary(contentsOfFile:plistPath)??NSDictionary() } var wrappedValue:Value{ 得到{ 将优先值(forKey:key)返回为?值??默认
@propertyWrapper结构说明符{
让键:字符串
让defaultValue:Value
让plistPath:String
var prefs:NSDictionary{
NSDictionary(contentsOfFile:plistPath)??NSDictionary()
}
var wrappedValue:Value{
得到{
将优先值(forKey:key)返回为?值??默认值
}
设置{
prefs.setValue(newValue,forKey:key)
prefs.write(toFile:plistPath,原子性:true)
}
}
}
我现在想在设置视图中使用此选项,如下所示:
struct PrefsView:View{
@说明符(键:“enable”,默认值:true,plistPath:“/Library/path/to/Prefs.plist”)私有变量enable
var body:一些观点{
形式{
切换(“启用”,isOn:$Enable)
}
}
}
我被告知以下错误:
Cannot find '$enable' in scope
我如何才能达到这样的效果,即写入和读取一个文件以设置和获取变量,同时允许它绑定到一个值
注意:我的项目不需要是“AppStore Legal”您的属性包装器返回
Bool
而不是Binding
,这是切换所需的
您可以指定projectedValue
(正如NewDev建议的那样)-这将允许您使用$
访问绑定
:
@propertyWrapper struct Specifier<Value> {
...
var wrappedValue: Value {
get {
projectedValue.wrappedValue
}
set {
projectedValue.wrappedValue = newValue
}
}
var projectedValue: Binding<Value> {
.init(get: {
prefs.value(forKey: key) as? Value ?? defaultValue
}, set: {
prefs.setValue($0, forKey: key)
prefs.write(toFile: plistPath, atomically: true)
})
}
}
struct ContentView: View {
@Specifier(key: "enable", defaultValue: true, plistPath: "/Library/path/to/Prefs.plist") private var enable
var body: some View {
Form {
Toggle("Enable", isOn: $enable)
Text(String(enable))
}
}
}
属性包装器返回Bool
而不是Binding
,这是切换所需的
您可以指定projectedValue
(正如NewDev建议的那样)-这将允许您使用$
访问绑定
:
@propertyWrapper struct Specifier<Value> {
...
var wrappedValue: Value {
get {
projectedValue.wrappedValue
}
set {
projectedValue.wrappedValue = newValue
}
}
var projectedValue: Binding<Value> {
.init(get: {
prefs.value(forKey: key) as? Value ?? defaultValue
}, set: {
prefs.setValue($0, forKey: key)
prefs.write(toFile: plistPath, atomically: true)
})
}
}
struct ContentView: View {
@Specifier(key: "enable", defaultValue: true, plistPath: "/Library/path/to/Prefs.plist") private var enable
var body: some View {
Form {
Toggle("Enable", isOn: $enable)
Text(String(enable))
}
}
}
感谢您的精彩、快速响应!只有一个问题:编译器现在希望defaultValue参数的类型为Binding
,因为您的解决方案当前生成了一个无法将类型为“Bool”的值转换为预期的参数类型“Binding”
错误。。。关于我如何解决这个问题,你有什么建议吗?@YulkyTulky请检查我如何在ContentView
中使用说明符
-推断出值
,你不需要调用@说明符
。哦,你完全正确!我试着不只是盲目地复制粘贴代码,并且没有注意到这个变化。。。非常感谢。您还可以将wrappedValue作为Bool
返回(正常情况下),并将投影值作为绑定返回
@NewDev谢谢,现在看起来更好了,因为在访问Bool值时不需要使用enable.wrappedValue
。感谢您的快速响应!只有一个问题:编译器现在希望defaultValue参数的类型为Binding
,因为您的解决方案当前生成了一个无法将类型为“Bool”的值转换为预期的参数类型“Binding”
错误。。。关于我如何解决这个问题,你有什么建议吗?@YulkyTulky请检查我如何在ContentView
中使用说明符
-推断出值
,你不需要调用@说明符
。哦,你完全正确!我试着不只是盲目地复制粘贴代码,并且没有注意到这个变化。。。非常感谢。您还可以将wrappedValue作为Bool
返回(正常情况下是这样),并将投影值作为绑定返回
@NewDev谢谢,现在看起来更好了,因为在访问Bool值时不需要使用enable.wrappedValue
。您可能会发现以下内容很有用。您可能会发现以下内容很有用。