Setting Max Input Length for TextField or TextEditor in SwiftUI

DevTechie Inc
May 11, 2023

TextFields and TextEditors are input controls in iOS and are used to get information from users.

SwiftUI provides data driven declarative approach to collect user information using TextField and TextEditor views. SwiftUI views come with a whole lot out of the box but at the same time, it provides a great foundation to build upon.

In this article, we will see a way to set max input character limit for both TextField and TextEditor.

We will start with two state properties.

maxChars : an integer type to set the maximum number of characters allowed in the view.

inputText : a string type to create binding property to capture user input.

public struct CharLimitTextEditor: View {
    
    @State private var maxChars: Int = 40
    @State private var inputText: String = "Learn iOS with DevTechie"

We will add a binding property inside body property with getter and setter. This is where we will set max char limit.

public var body: some View {
    let text = Binding(
        get: { self.inputText },
        set: { self.inputText = String($0.prefix(maxChars))}
    )

Our TextField or TextEditor will bind to the text binding property created inside the body property.

Complete view will look like this:

public struct CharLimitTextEditor: View {
    
    @State private var maxChars: Int = 40
    @State private var inputText: String = "Learn iOS with DevTechie"
    
    public var body: some View {
        let text = Binding(
            get: { self.inputText },
            set: { self.inputText = String($0.prefix(maxChars))}
        )
        
        NavigationStack {
            VStack {
                Text("Number of chars : \(text.wrappedValue.count)")
                    .foregroundColor(text.wrappedValue.count == maxChars ? .red : .primary)
                TextField("", text: text)
                    .textFieldStyle(.roundedBorder)
            }
            .navigationTitle("DevTechie")
            .padding()
        }
    }
}

Build and run

We can swap TextField with TextEditor and use the same technique to limit number of char allowed in TextEditor.

public struct CharLimitTextEditor: View {
    
    @State private var maxChars: Int = 100
    @State private var inputText: String = "Learn iOS with DevTechie"
    
    public var body: some View {
        let text = Binding(
            get: { self.inputText },
            set: { self.inputText = String($0.prefix(maxChars))
            }
        )
        
        NavigationStack {
            VStack {
                Text("Number of chars : \(text.wrappedValue.count)")
                    .foregroundColor(text.wrappedValue.count == maxChars ? .red : .primary)
                TextEditor(text: text)
            }
            .navigationTitle("DevTechie")
            .padding()
        }
    }
}

In the case of TextEditor, we can limit carriage return as well by adding sepearatedBy components function to String.

public struct CharLimitTextEditor: View {
    
    @State private var maxChars: Int = 100
    @State private var inputText: String = "Learn iOS with DevTechie"
    
    public var body: some View {
        let text = Binding(
            get: { self.inputText },
            set: { self.inputText = String($0.prefix(maxChars))
                    .components(separatedBy: .newlines).joined()
            }
        )
        
        NavigationStack {
            VStack {
                Text("Number of chars : \(text.wrappedValue.count)")
                    .foregroundColor(text.wrappedValue.count == maxChars ? .red : .primary)
                TextEditor(text: text)
            }
            .navigationTitle("DevTechie")
            .padding()
        }
    }
}