admin管理员组

文章数量:1026381

I'm struggling with a simple task, to restrict TextField input with integers only. From the description - dounds easy. However, I can't find a way to do it with SwiftUI. I have an app macOS app with AppKit and want to re-write to SwiftUI. In my original code I use Combine and check NSTextField input in: textViewDidChangeSelection

Than -> I inform my viewModel about what about to be typed - do the validation and assign the value if it's a correct one.

Unfortunately, I can't do the same with SwiftUI for some reasons. The problem is: I'm still allowed to type anything in TextField -> but as soon as I "leave it"/change focus -> it does filter to what I need. However, my goal is to NOT allow anything to be typed in TextField, apart from integers.

I've tried everything: ChatGPT suggestions, simple solutions like this: It still does not work and allow me to type eveyrthing, until I change focus from TextField to something else -> only than in gets filtered.

Am I missing something? Any help will be appreciated.

Code is below:

import SwiftUI
import Combine

struct ContentView: View {
    @ObservedObject var viewModel: TestViewModel
    var body: some View {
        VStack {
            InputTextFieldSwiftUIView(
                label: "Ints only field",
                text: Binding<String> {
                    return viewModel.text.intOnlyText
                } set: { newText in
                    viewModel.validateText(newText)
                },
                onTextChanged: { newValue in
                    // What should I do here?
                }
            )
        }
    }
}

struct MyTestText {
    var intOnlyText: String
}


class TestViewModel: ObservableObject {
    @Published var text = MyTestText(intOnlyText: "")
    
    func validateText(_ textValue: String) {
        if textValue.isInt() || textValue.isEmpty {
            text.intOnlyText = textValue
        } else {
            text.intOnlyText = text.intOnlyText
        }
    }
}

private extension String {
    
    func isInt() -> Bool {

        if let intValue = Int(self) {
            if intValue > 0 {
                return true
            }
        }
        return false
    }
}


struct InputTextFieldSwiftUIView: View {
    var label: String
    @Binding var text: String
    
    let onTextChanged: (String) -> Void
    
    var body: some View {
        
        HStack {
            Text(label)
                .font(.headline)
                .frame(width: 100, alignment: .leading)
            TextField("", text: $text)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .frame(width: 100)
                .padding()
                .onChange(of: text) { newValue in
                    onTextChanged(newValue)
                }
        }
    }
}

I'm struggling with a simple task, to restrict TextField input with integers only. From the description - dounds easy. However, I can't find a way to do it with SwiftUI. I have an app macOS app with AppKit and want to re-write to SwiftUI. In my original code I use Combine and check NSTextField input in: textViewDidChangeSelection

Than -> I inform my viewModel about what about to be typed - do the validation and assign the value if it's a correct one.

Unfortunately, I can't do the same with SwiftUI for some reasons. The problem is: I'm still allowed to type anything in TextField -> but as soon as I "leave it"/change focus -> it does filter to what I need. However, my goal is to NOT allow anything to be typed in TextField, apart from integers.

I've tried everything: ChatGPT suggestions, simple solutions like this: It still does not work and allow me to type eveyrthing, until I change focus from TextField to something else -> only than in gets filtered.

Am I missing something? Any help will be appreciated.

Code is below:

import SwiftUI
import Combine

struct ContentView: View {
    @ObservedObject var viewModel: TestViewModel
    var body: some View {
        VStack {
            InputTextFieldSwiftUIView(
                label: "Ints only field",
                text: Binding<String> {
                    return viewModel.text.intOnlyText
                } set: { newText in
                    viewModel.validateText(newText)
                },
                onTextChanged: { newValue in
                    // What should I do here?
                }
            )
        }
    }
}

struct MyTestText {
    var intOnlyText: String
}


class TestViewModel: ObservableObject {
    @Published var text = MyTestText(intOnlyText: "")
    
    func validateText(_ textValue: String) {
        if textValue.isInt() || textValue.isEmpty {
            text.intOnlyText = textValue
        } else {
            text.intOnlyText = text.intOnlyText
        }
    }
}

private extension String {
    
    func isInt() -> Bool {

        if let intValue = Int(self) {
            if intValue > 0 {
                return true
            }
        }
        return false
    }
}


struct InputTextFieldSwiftUIView: View {
    var label: String
    @Binding var text: String
    
    let onTextChanged: (String) -> Void
    
    var body: some View {
        
        HStack {
            Text(label)
                .font(.headline)
                .frame(width: 100, alignment: .leading)
            TextField("", text: $text)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .frame(width: 100)
                .padding()
                .onChange(of: text) { newValue in
                    onTextChanged(newValue)
                }
        }
    }
}

本文标签: SwiftUI macOS TextFieldrestrict input to integers onlyStack Overflow