It's a bit modification for the @jfk's answer, we can create an extension for view to simplify the modifier code inside the main view and also it can be used for Text and Image.
struct PlaceHolder<T: View>: ViewModifier {
var placeHolder: T
var show: Bool
func body(content: Content) -> some View {
ZStack(alignment: .leading) {
if show { placeHolder }
content
}
}
}
extension View {
func placeHolder<T:View>(_ holder: T, show: Bool) -> some View {
self.modifier(PlaceHolder(placeHolder:holder, show: show))
}
}
Usage in TextField:
Add this line of code .placeHolder(Text("Your placeholder"), show: text.isEmpty) as a viewModifier to TextField.
If you want to preserve the original TextField and you don't mind adding Introspect to your project (https://github.com/siteline/SwiftUI-Introspect), you can do it by accessing the UIKit attributedPlaceholder: