SwiftUI TextField 数字输入

SwiftUI TextField Number Input

我试图让用户输入两个数字,然后显示这些数字并将它们相加。目前,为了更新状态变量,您需要按 return。有没有办法像处理文本一样更新状态?我也将代码作为字符串输入,但无法将其转换为 int,因此无法正确地将数字相加。如果有人知道如何正确转换它,我将不胜感激我能得到的所有帮助。

struct ContentView: View {
    @State private var numOne: Int = 0
    @State private var numTwo: Int = 0

    var body: some View {
        NavigationView {
            VStack {
                Form {
                    Section {
                        TextField("Number One", value: $numOne, formatter: NumberFormatter())
                            .keyboardType(.numberPad)

                        TextField("Number Two", value: $numTwo, formatter: NumberFormatter())
                            .keyboardType(.numberPad)
                    }

                    NavigationLink(
                        destination: addedView(numOne: $numOne, numTwo: $numTwo),
                        label: {
                            Text("Navigate")
                        }
                    )
                }
            }
        }
    }
}

struct addedView: View {
    @Binding var numOne: Int
    @Binding var numTwo: Int
    @State private var added: Int = 0

    var body: some View {
        VStack {
            Text("\(numOne)")
            Text("\(numTwo)")
        }
    }
}

这使用 Combine 来确保输入的文本是数字,然后将其更改为 Int 以用于计算。 return 值是一个闭包,您可以使用它来

struct EditableInt : View {

    var intString: String = ""
    var onChanged: (Int) -> Void

    init(_ int: Int?, onChanged: @escaping (Int) -> Void) {
        if let int = int,
           let formattedInt = Formatter.numberFormatter.string(from: int as NSNumber){
            self.intString = formattedInt
        } else {
            intString = ""
        }
        self.onChanged = onChanged
    }
    
    @State private var editableInt: String = ""

    var body: some View {
            TextField(" " + intString + " ", text: $editableInt)
            .onReceive(Just(editableInt)) { newValue in
                let editableInt = newValue.filter { "0123456789".contains([=10=]) }
                if editableInt != intString {
                    if let returnInt = Int(editableInt) {
                        onChanged(returnInt)
                    }
                }
            }
        .onAppear { self.editableInt = self.intString }
    }
}

以上是可重用的,从另一个视图调用是这样的:

struct OtherView: View {

    @State var otherViewInt = 0

        var body: some View {
            EditableInt(otherViewInt) { newInt in
                otherViewInt = newInt
            }
        }
}

这说明了如何强制 TextField 为整数,以及如何将它们相加得到一个结果。

主要区别在于格式化程序的 numberStyle.decimal。这意味着您只会得到整数/整数。

结果是 Int 时添加的,因此添加了 个数字 。如果您在它们都是 String 时添加,它们将 连接 在一起。例如。您希望 5 + 10 成为 15,而不是 510

然后您可以将 result 传递给子视图或 NavigationLink 如果您愿意。

struct ContentView: View {
    @State private var numOne: Int = 0
    @State private var numTwo: Int = 0

    private static let formatter: NumberFormatter = {
        let formatter = NumberFormatter()
        formatter.numberStyle = .decimal
        return formatter
    }()

    private var result: Int {
        numOne + numTwo
    }

    var body: some View {
        NavigationView {
            VStack {
                Form {
                    Section {
                        TextField("Number One", value: $numOne, formatter: Self.formatter)
                            .keyboardType(.numberPad)

                        TextField("Number Two", value: $numTwo, formatter: Self.formatter)
                            .keyboardType(.numberPad)
                    }

                    Section {
                        Text("Result: \(result)")
                    }
                }
            }
        }
    }
}

请注意,NumberFormatter 是静态创建的,并且仅创建一次。这是因为创建它们非常昂贵,尤其是两次每个渲染。