avatar
Published on

Adding a character limit to a TextEditor or TextField in SwiftUI

Authors
  • avatar
    Name
    Mick MacCallum
    Twitter
    @0x7fs

It is common to need to create a text input that limits the number of characters that a user can enter. This could be for a social post or a password field in a login form. SwiftUI currently doesn't provide a built-in way of limited the number of characters that can be entered in either the TextEditor or TextField views, but luckily we can still easily add this functionality.

Using the onChange modifier, we can subscribe to changes in the text editor/field's text and when it changes, override the text with only the first n characters. For example, if we wanted to add a 50 character limit to a TextEditor, we could use the following.

struct ContentView: View {
    @State var text: String = ""

    var body: some View {
        TextEditor(text: $text)
            .onChange(of: text) {
                text = String(text.prefix(50))
            }
    }
}

To make this code reusable, we can create a new characterLimit view modifier that takes the view's text binding and the character limit as inputs.

extension View {
    func characterLimit(_ text: Binding<String>, to limit: Int) -> some View {
        onChange(of: text.wrappedValue) {
            text.wrappedValue = String(text.wrappedValue.prefix(limit))
        }
    }
}

The new modifier can then be used to limit the characters entered on both TextField and TextEditor views.

struct ContentView: View {
    @State var title: String = ""
    @State var body: String = ""

    var body: some View {
        TextField(text: $title)
            .characterLimit($title, to: 20)

        TextEditor(text: $body)
            .characterLimit($body, to: 140)
    }
}