SwiftUI
TextField
multiline
iOS Development
Swift Programming

How do I create a multiline TextField in SwiftUI?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In current SwiftUI, you have two good options for multiline text input. Use TextField with axis: .vertical when you want a field that can grow to a few lines, and use TextEditor when you want a true large text area for notes, comments, or message composition.

Use TextField with a vertical axis

Modern SwiftUI supports an expanding text field directly:

swift
1import SwiftUI
2
3struct GrowingFieldView: View {
4    @State private var text = ""
5
6    var body: some View {
7        TextField("Enter a message", text: $text, axis: .vertical)
8            .textFieldStyle(.roundedBorder)
9            .lineLimit(3...6)
10            .padding()
11    }
12}

This is the closest thing to a multiline TextField. The field starts compact, expands vertically as the user types, and can be constrained with lineLimit.

This approach is a good fit when:

  • you still conceptually want a field, not a large editor
  • the content is expected to stay fairly short
  • you want standard TextField behavior such as submit handling

Use TextEditor for true long-form input

If the content might be paragraphs long, TextEditor is usually the better control:

swift
1import SwiftUI
2
3struct NotesView: View {
4    @State private var notes = ""
5
6    var body: some View {
7        TextEditor(text: $notes)
8            .frame(minHeight: 160)
9            .padding(8)
10            .overlay(
11                RoundedRectangle(cornerRadius: 8)
12                    .stroke(Color.gray.opacity(0.4))
13            )
14            .padding()
15    }
16}

TextEditor behaves more like UITextView from UIKit. It is designed for multiline editing first, not as an enhanced single-line field.

That makes it the better choice for:

  • notes
  • descriptions
  • feedback forms
  • chat drafts
  • any input that may grow beyond a few lines

Add placeholder behavior when using TextEditor

One difference is that TextEditor does not have a built-in placeholder the way TextField does. A common SwiftUI pattern is to layer placeholder text behind the editor:

swift
1import SwiftUI
2
3struct EditorWithPlaceholder: View {
4    @State private var notes = ""
5
6    var body: some View {
7        ZStack(alignment: .topLeading) {
8            if notes.isEmpty {
9                Text("Write your notes here...")
10                    .foregroundStyle(.secondary)
11                    .padding(.top, 16)
12                    .padding(.leading, 20)
13            }
14
15            TextEditor(text: $notes)
16                .padding(8)
17        }
18        .frame(minHeight: 180)
19        .overlay(
20            RoundedRectangle(cornerRadius: 8)
21                .stroke(Color.gray.opacity(0.4))
22        )
23        .padding()
24    }
25}

This is often enough for production UI, especially when paired with validation and character-count feedback.

Decide between the two controls intentionally

The question is not just "how do I make it multiline?" It is also "what editing experience do I want?"

Use TextField(axis: .vertical) when you want a compact field that can stretch a bit. Think message subjects, short comments, or reply boxes with limited expected length.

Use TextEditor when you want a dedicated editing surface. Think descriptions, notes, or any content the user may scroll through and revise more heavily.

That distinction matters because the control choice affects selection behavior, placeholder handling, scrolling, and overall feel.

Focus and keyboard handling

Both controls work with SwiftUI focus APIs. Here is a simple example with TextEditor:

swift
1import SwiftUI
2
3struct FocusedEditorView: View {
4    @State private var text = ""
5    @FocusState private var isFocused: Bool
6
7    var body: some View {
8        VStack {
9            TextEditor(text: $text)
10                .frame(height: 150)
11                .focused($isFocused)
12
13            Button("Focus editor") {
14                isFocused = true
15            }
16        }
17        .padding()
18    }
19}

That makes it easier to control first-responder behavior in forms or compose screens.

Common Pitfalls

The biggest mistake is assuming old advice that "TextField is single-line only" is still the whole story. That was broadly true before SwiftUI gained the vertical-axis initializer, but not for current releases.

Another common issue is forcing TextEditor into a field-shaped UI without accounting for placeholder behavior and height management.

People also choose TextField(axis: .vertical) for very long content, then run into awkward scrolling or editing limits. At that point, TextEditor is usually the better control.

Finally, styling can be misleading. TextEditor does not automatically look like a standard TextField, so you often need to add borders or background styling yourself.

Summary

  • Use TextField(..., axis: .vertical) for a field that can grow across a few lines.
  • Use TextEditor for true multiline, long-form text entry.
  • Add your own placeholder layer when using TextEditor.
  • Pick the control based on editing behavior, not just visual appearance.
  • Use SwiftUI focus APIs to manage keyboard and first-responder behavior cleanly.

Course illustration
Course illustration

All Rights Reserved.