Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jsp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 如何使自定义属性包装可以绑定,可能是使用@State?_Swift_Properties_Swiftui_State_Property Wrapper - Fatal编程技术网

Swift 如何使自定义属性包装可以绑定,可能是使用@State?

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)返回为?值??默认

我已经创建了一个自定义属性包装器,它作为文件的setter和getter从文件中进行写入和读取

@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
。您可能会发现以下内容很有用。您可能会发现以下内容很有用。