Binding 在SwiftUI中构建可重用组件的问题

Binding 在SwiftUI中构建可重用组件的问题,binding,swiftui,Binding,Swiftui,我试图使用SwiftUI构建一个可重用的组件,我以前用@IBDesignable实现过这个组件,但事实证明这比我想象的要困难得多。问题是a)初始化文本变量和b)剪裁计数值。请参阅下面的代码 我尝试过根据计数值的变化在初始值设定项和主体闭包中修改文本变量的值,但这两种方法都不允许 count值的限制和文本变量的初始化需要在视图内部以及视图的客户端修改count值时进行。当客户机视图修改计数时,我不知道如何实现这一点 @Binding var count: Int @State va

我试图使用SwiftUI构建一个可重用的组件,我以前用@IBDesignable实现过这个组件,但事实证明这比我想象的要困难得多。问题是a)初始化文本变量和b)剪裁计数值。请参阅下面的代码

我尝试过根据计数值的变化在初始值设定项和主体闭包中修改文本变量的值,但这两种方法都不允许

count值的限制和文本变量的初始化需要在视图内部以及视图的客户端修改count值时进行。当客户机视图修改计数时,我不知道如何实现这一点

    @Binding var count: Int
    @State var text : String = ""
    var maxVal = 5
    var minVal = -5

    var body: some View {
        VStack {
            TextField($text,
                      onEditingChanged: validateString
            )
                .frame(maxWidth: .infinity, maxHeight: .infinity)
            HStack {
                Button(
                    action: { self.add(1) },
                    label: { Text("Plus")}
                )
                Button(
                    action: { self.add(-1) },
                    label: { Text("Minus")}
                )
            }
        }
    }

    func setVal(_ num: Int) {
        count = min(max(num, minVal), maxVal)
        if text != String(count) { text = String(count) }
    }

    func validateString(_ flag: Bool) {
        if !flag {
            guard let num = Int(text) else { return }
            setVal(num)
        }
    }

    func add(_ increment: Int) {
        setVal(count + increment)
    }

}

如果我了解了绑定的所有内部细节以及SwiftUI如何重建视图,我相信我能够解决这个问题。但这是创建自动“it just works”框架的缺点之一。我对SwiftUI感到非常兴奋,并希望在理解上克服这一障碍。

您遗漏了部分代码,特别是您试图初始化视图的方式。但这应该让你开始

还请注意,在您离开文本字段(或隐藏键盘)之前,不会调用onEditingChanged,因此在此之前不会进行剪辑。

我还注意到您使用的是一个旧的TextField初始值设定项,它已经被弃用了。我更新了它的新版本

导入快捷界面
结构ContentView:View{
@国家私有变量计数=3
var body:一些观点{
MyView(计数:$count)
}
}
结构MyView:View{
@绑定变量计数:Int
@国家私有变量文本:字符串
var maxVal=5
var minVal=-5
初始化(计数:绑定){
自计数=计数
self.\u text=状态(初始值:“\(count.value)”)
}
var body:一些观点{
VStack{
TextField(“,text:$text,onEditingChanged:validateString)
.textFieldStyle(.roundedBorder)
.frame(maxWidth:无穷大,maxHeight:无穷大)
HStack{
钮扣(
动作:{self.add(1)},
标签:{Text(“Plus”)}
)
钮扣(
操作:{self.add(-1)},
标签:{Text(“减号”)}
)
}
}
}
func setVal(num:Int){
计数=最小值(最大值(num,minVal),maxVal)
如果text!=String(count){text=String(count)}
}
func validateString(uflag:Bool){
如果!旗帜{
guard let num=Int(text)else{return}
setVal(num)
}
}
func add(u增量:Int){
setVal(计数+增量)
}
}

因此,基本上您忘记了为可重用组件添加一个
init()
。默认情况下,使用结构中声明的属性的初始值设定项创建结构。但是如果您想构建一个可重用的组件,您需要添加一个
init()
。当我创建一个可重用SwiftUI组件的自定义库,然后在我的项目中使用它时,它帮助了我。因此,我的库中的公共结构必须包含一个
init()

我试图复制并运行您发送的修改后的代码。但它甚至无法建造。我得到类型为“MyView”的
值没有成员“\u count”
,self的错误与此相同。我本来想问你这个下杆语法是从哪里来的,但它似乎不正确。另外,我看不出有任何工具可以限制计数,当它由客户端ContentView设置时,这是我问的另一件事。也许这不是限制值的“快速UI方式”——这是我熟悉的“自定义UI控件”模型,我习惯于使用代码编译。但很明显,您使用的是旧版本的Xcode。最后一次更新是Beta 4。一些方法被弃用,新方法被添加,一些实现(如属性包装器被更改)。这最后一个变化是什么使下面的代码,而不是美元符号的必要。我建议你升级到最新版本时,张贴一个问题在这里,这样的答案将相关更长的时间。至于你关于限制数量的另一个问题,我不确定我是否理解。也许你可以添加一些伪代码来展示你想要实现的目标。首先,我为不知道Xcode beta 4而道歉。不幸的是,当我试图创建一个包含上述代码的Xcode项目时,它会反复崩溃。我正在创建一个简单的MacOS SwiftUI项目。我想,一旦Xcode和API稳定下来,我就必须回到这里。同时,我对初始值设定项中的下划线表示法很好奇。这是什么意思?是否有文件记录?最后,客户端修改时限制(剪裁)count值的问题最好通过示例来解释,因为XCode4正在崩溃,所以我现在无法创建该示例。可能它崩溃了,因为我还需要更新Catalina,但我现在不能这样做,因为我在国外的互联网速度很慢。不,我尝试了各种自定义初始值设定方法,但它们的行为似乎也不符合预期。你能找到一个能正确使用上述例子的方法吗?我是否应该发布另一个自定义初始值设定项无效的示例?FWIW,除了一个textField,我没有遇到过这个问题,大概是因为它需要一个绑定,因此变量必须是@state变量。