英文:
Pass an @State variable as parameter and change its value inside a function
问题
I can provide the translation for the code portion you provided:
我试图验证文本字段,只允许输入数字、一个小数点或一个逗号。在下面的代码中,我有两个 `TextField`,`textFieldOne` 和 `textFieldTwo`,在 `textFieldOne` 中,我通过调用 `validateField()` 方法来验证字段,一切都按预期工作,因为我在 `validateField()` 方法内修改了它的值。但我试图让 `validateField()` 方法更加模块化,并能够传递一个 `State` 变量,以便可以在多个字段中使用它,以避免代码重复,但我一直没有找到一种在 `validateField()` 方法中将 `State` 变量作为参数传递的方法。我尝试将其传递为 `validateField(textFieldName: Binding<String> ,newValue:String)`,但我收到错误消息,说它无法将类型 `'String'` 转换为预期的类型 `'Binding<String>`。
如何将 `@State` 的 `textFieldOne` 和 `textFieldTwo` 作为参数传递给 `validateField()` 方法?
再次强调,我想要的是能够在每个字段的 `.onChange` 修饰符内调用 `validateField()` 方法,类似于这样... `validateField(fieldName:textFieldOne, newValue: newValue)`。基本上,使该方法可重用。
Please note that I've translated the code portion you provided. If you have any further questions or need assistance with this code, please feel free to ask.
英文:
I'm trying to validate textFields to only allow numbers, a single period, or a single comma. In the code below I have two TextField
s, textFieldOne
and textFieldTwo
, in textFieldOne
I'm validating the field by calling the validateField()
method, everything works as expected for textFieldOne since I'm modifying its value inside the validateField()
method, but what I'm trying to do is make the validateField()
method more modular and be able to pass a State
variable to be able to use it with multiple fields to avoid code duplication but I haven't been able to figure out a way to pass the State
variable as a parameter in the validateField()
method. I tried passing it as validateField(textFieldName: Binding<String> ,newValue:String)
but I got errors saying that it couldn't convert type 'String' to expected type 'Binding<String>
.
How can I pass @State
textFieldOne and textFieldOne respectably as a parameter in the validateField()
method?
Again, what I'm trying to do is be able to call the validateField()
method inside the .onChange
modifier of each field, something like this... validateField(fieldName:textFieldOne, newValue: newValue)
. Basically, make the method reusable.
struct TextFieldNumbersOnly: View {
@State private var textFieldOne = ""
@State private var textFieldTwo = ""
var body: some View {
Form{
TextField("field one", text: $textFieldOne)
.keyboardType(.decimalPad)
.onChange(of: textFieldOne){newValue in
validateField(newValue: newValue)
}
TextField("field two", text: $textFieldTwo)
.keyboardType(.decimalPad)
.onChange(of: textFieldTwo){newValue in
//validateField(newValue: newValue)
}
}
}
func validateField(newValue:String){
let periodCount = newValue.components(separatedBy: ".").count - 1
let commaCount = newValue.components(separatedBy: ",").count - 1
if newValue.last == "." && periodCount > 1 || newValue.last == "," && commaCount > 1{
//it's a second period or comma, remove it
textFieldOne = String(newValue.dropLast())
}else{
let filtered = newValue.filter { "0123456789.,".contains($0) }
if filtered != newValue{
self.textFieldOne = filtered
}
}
}
}
答案1
得分: 0
你可以尝试这种替代方法,以实现你想要的效果,只允许文本字段包含数字、一个小数点或一个逗号,并使函数 validateField(...)
更加模块化。
这种方法简单地使用了一个修改过的函数 validateField(...)
,该函数返回已验证的字符串,如示例代码所示。它很干净,并且执行函数应该执行的操作,即接受一个 String
输入并返回一个经过验证的输出。
struct TextFieldNumbersOnly: View {
@State private var textFieldOne = ""
@State private var textFieldTwo = ""
var body: some View {
Form {
TextField("field one", text: $textFieldOne)
.keyboardType(.decimalPad)
.onChange(of: textFieldOne){ newValue in
textFieldOne = validateField(newValue) // <-- 这里
}
TextField("field two", text: $textFieldTwo)
.keyboardType(.decimalPad)
.onChange(of: textFieldTwo){ newValue in
textFieldTwo = validateField(newValue) // <-- 这里
}
}
}
func validateField(_ newValue: String) -> String { // <-- 这里
let periodCount = newValue.components(separatedBy: ".").count - 1
let commaCount = newValue.components(separatedBy: ",").count - 1
if newValue.last == "." && periodCount > 1 || newValue.last == "," && commaCount > 1 {
// 这是第二个小数点或逗号,移除它
return String(newValue.dropLast()) // <-- 这里
} else {
let filtered = newValue.filter { "0123456789., ".contains($0) }
if filtered != newValue {
return filtered // <-- 这里
}
}
return newValue // <-- 这里
}
}
希望这对你有所帮助。如果有其他问题,请随时提问。
英文:
You could try this alternative approach, to achieve what you want, ...to validate textFields
to only allow numbers, a single period, or a single comma
and to make the function validateField(...)
more modular.
The approach simply uses a modified function validateField(...)
that
returns the validated String, as shown in the example code.
It's clean and do what the function is supposed to do,
take a String
input and returns a validated one as output.
struct TextFieldNumbersOnly: View {
@State private var textFieldOne = ""
@State private var textFieldTwo = ""
var body: some View {
Form {
TextField("field one", text: $textFieldOne)
.keyboardType(.decimalPad)
.onChange(of: textFieldOne){ newValue in
textFieldOne = validateField(newValue) // <-- here
}
TextField("field two", text: $textFieldTwo)
.keyboardType(.decimalPad)
.onChange(of: textFieldTwo){ newValue in
textFieldTwo = validateField(newValue) // <-- here
}
}
}
func validateField(_ newValue: String) -> String { // <-- here
let periodCount = newValue.components(separatedBy: ".").count - 1
let commaCount = newValue.components(separatedBy: ",").count - 1
if newValue.last == "." && periodCount > 1 || newValue.last == "," && commaCount > 1 {
//it's a second period or comma, remove it
return String(newValue.dropLast()) // <-- here
} else {
let filtered = newValue.filter { "0123456789.,".contains($0) }
if filtered != newValue{
return filtered // <-- here
}
}
return newValue // <-- here
}
}
答案2
得分: 0
创建一个新的视图,并在其中放置一个文本字段和验证。请注意,SwiftUI 的设计是在 onSubmit 中进行验证,而不是在 onChange 中进行验证,以允许粘贴。然后使用两个这样的视图。
TextFieldNumbersOnly(text: $one)
TextFieldNumbersOnly(text: $two)
struct TextFieldNumbersOnly: View {
@Binding private var text: String
var body: some View {
TextField("字段", text: $text)
.keyboardType(.decimalPad)
.onSubmit {
validate()
}
}
func validate(){
...
英文:
Create a new View and put one TextField and the validation in it. FYI SwiftUI is designed to do validation in onSubmit instead of onChange to allow pasting. Then use two of these Views.
TextFieldNumbersOnly(text: $one)
TextFieldNumbersOnly(text: $two)
struct TextFieldNumbersOnly: View {
@Binding private var text: String
var body: some View {
TextField("field", text: $text)
.keyboardType(.decimalPad)
.onSubmit {
validate()
}
}
func validate(){
…
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论