NEW BOOK! Swift Gems: 100+ tips to take your Swift code to the next level. Learn more ...NEW BOOK! Swift Gems:100+ advanced Swift tips. Learn more...

Add placeholder text to SwiftUI TextEditor

In iOS 14 we got a new SwiftUI view TextEditor that lets us display and edit multiline, scrollable text. As of iOS 14 beta 4 it doesn't have an API to define the placeholder text for it. In this article we will see how we can add one ourselves.

Swift Gems by Natalia Panferova book coverSwift Gems by Natalia Panferova book cover

Check out our new book!

Swift Gems

100+ tips to take your Swift code to the next level

Swift Gems

100+ tips to take your Swift code to the next level

  • Advanced Swift techniques for experienced developers bypassing basic tutorials
  • Curated, actionable tips ready for immediate integration into any Swift project
  • Strategies to improve code quality, structure, and performance across all platforms
  • Practical Swift insights from years of development, applicable from iOS to server-side Swift

First we will create a TextEditor view and give it a background color of our choice. On IOS 14 beta 4 TextEditor has a default background that can only be unset through UITextView appearance property.

struct ContentView: View {
    @State private var text = ""
    
    init() {
        UITextView.appearance().backgroundColor = .clear
    }
    
    var body: some View {
        ZStack(alignment: .topLeading) {
            RoundedRectangle(cornerRadius: 8, style: .continuous)
                .fill(Color(UIColor.secondarySystemBackground))
            
            TextEditor(text: $text)
                .padding(4)
            
        }
        .frame(width: 300, height: 400)
        .font(.body)
    }
}

Now we just need to check if the text in the editor is empty and insert our placeholder text view. We have to make sure that the placeholder view is inserted in the ZStack before TextEditor so that it's underneath TextEditor on screen. This way it won't intercept the taps.

struct ContentView: View {
    @State private var text = ""
    
    init() {
        UITextView.appearance().backgroundColor = .clear
    }
    
    var body: some View {
        ZStack(alignment: .topLeading) {
            RoundedRectangle(cornerRadius: 8, style: .continuous)
                .fill(Color(UIColor.secondarySystemBackground))
            
            if text.isEmpty {
                Text("Placeholder Text")
                    .foregroundColor(Color(UIColor.placeholderText))
                    .padding(.horizontal, 8)
                    .padding(.vertical, 12)
            }
            
            TextEditor(text: $text)
                .padding(4)
            
        }
        .frame(width: 300, height: 400)
        .font(.body)
    }
}