0

Hi i am creating a to do application and i am facing a problem when a user entering some characters to a UIText field i remember there was a way in SWIFT 5 to put a max length but i can't find one in SWIFT UI can someone send me a link or guide me step by step HOW CAN I ADD A MAX LENTGH TO A SWIFT UI PROJECT TO THE TEXT FIELD! THANKS

I tried to find it Everywhere but i can't

struct NewTaskView: View { var taskStore: TaskStore

@Environment(\.presentationMode) var presentationMode


@State var text = ""
@State var priority: Task.Priority = .Низкий


var body: some View {
    Form {
        TextField("Название задания", text: $text)


        VStack {
            Text("Приоритет")
                .multilineTextAlignment(.center)
            Picker("Priority", selection: $priority.caseIndex) {
                ForEach(Task.Priority.allCases.indices) { priorityIndex in
                    Text(
                        Task.Priority.allCases[priorityIndex].rawValue
                        .capitalized
                    )
                    .tag(priorityIndex)
                }
            }
            .pickerStyle( SegmentedPickerStyle() )
        }

I want to put max length to a text field where is written TextField("Название задания", text: $text)

2 Answers2

0

It seems like this can be achieved with Combine, by creating a wrapper around the text and opening a 2 way subscription, with the text subscribing to the TextField and the TextField subscribing to the ObservableObject. I'd say the way it works its quite logical from a Reactive point of view but would have liked to find a cleaner solution that didn't require another object to be created.

import SwiftUI
import Combine

class TextBindingManager: ObservableObject {
    @Published var text = "" {
        didSet {
            if text.count > characterLimit && oldValue.count <= characterLimit {
                text = oldValue
            }
        }
    }
    let characterLimit = 5
}

struct ContentView: View {
    @ObservedObject var textBindingManager = TextBindingManager()

    var body: some View {
        TextField("Placeholder", text: $textBindingManager.text)
    }
}
Alex Ioja-Yang
  • 1,428
  • 13
  • 28
  • That's a number you can set, whether replace locally with your limit, or whether you want to declare as a property: `let characterLimit = 4` – Alex Ioja-Yang Oct 13 '19 at 11:03
  • Replace the if line with `if text.count > 4 && oldValue.count <= 4 {` and it will compile and should work. Alternatively, within your object you can declare a constant (see my previous comment) and use it to compare against. That would allow you to reuse it easily, get a consistent limit if you need to use it multiple times, as well as making it easier to change and update when needed, without digging through code. – Alex Ioja-Yang Oct 13 '19 at 11:05
  • Can i send you my project trough mail can you take a look i am sorry i just started to learn Swift UI i am still stucked with structure and implementing code – Nursultan Yelemessov Oct 13 '19 at 11:36
  • Sorry, the reason it worked in my project was that I was using an `EnvironmentObject` to wrap the String. Created a project from scratch and got a working solution, see my edited answer. I do find SwiftUI to be very counterintuitive with some simple things. You end up saving a lot of time on complex issues, but that's balanced with spending a lot longer than usual for simple tasks – Alex Ioja-Yang Oct 13 '19 at 14:11
  • Yeah that so crazy. I have 2 problems now dismissal of the keyboard and setting up a max length for a characters in SWIFT UI! there is nothing upon this 2 files!!!:(( – Nursultan Yelemessov Oct 13 '19 at 14:40
  • its not working! because my app is a todo app and as soon as i implement this part of the code the limit is working but i can't add it to my list which is a content view! – Nursultan Yelemessov Oct 13 '19 at 15:13
  • I'm not sure I understand, "this part of the code the limit is working but i can't add it to my list which is a content view" – Alex Ioja-Yang Oct 13 '19 at 15:49
0

I read this article. please check here

This is my whole code. I don't use EnvironmentObject.

struct ContentView: View {
    @ObservedObject private var restrictInput = RestrictInput(5)
    var body: some View {
        Form {
            TextField("input text", text: $restrictInput.text)
        }
    }

class RestrictInput: ObservableObject {
    @Published var text = ""
    private var canc: AnyCancellable!
    init (_ maxLength: Int) {
        canc = $text
            .debounce(for: 0.5, scheduler: DispatchQueue.main)
            .map { String($0.prefix(maxLength)) }
            .assign(to: \.text, on: self)
    }
    deinit {
        canc.cancel()
    }
}
Masanao Imai
  • 125
  • 2
  • 2