SwiftUIで複数行の入力を行いたい時はTextEditorを使おう

前にUITextViewの記事を書いた時にSwiftUIだとどうやるんだ?と思ったのでやる。

tokizuoh.hatenablog.com

開発環境

> xcodebuild -version
Xcode 13.1
Build version 13A1030d

記事中のスクリーンショット: iPhone 13 Pro Max / iOS15.0

TextFieldのheightは変更できない

SwiftUIでUITextViewを模倣するためにTextFieldを使おうと試みたが、heightの変更が上手く効かない。

import SwiftUI

struct ContentView: View {
    
    @State private var text: String = ""
    
    var body: some View {
        ZStack(alignment: .center) {
            Color.gray
                .ignoresSafeArea()
            
            TextField("Please input text here.",
                      text: $text)
                .background(Color.white)
                .frame(width: 250,
                       height: 250)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
            .background(Color.gray)
    }
}

f:id:tokizuoh:20220226121838p:plain

明らかに縦横比が1:1でない。

Rectangleではどうか?

heightが他のViewでも変えられないか試すためにRectangleを使った。

import SwiftUI

struct ContentView: View {
    
    @State private var text: String = ""
    
    var body: some View {
        ZStack(alignment: .center) {
            Color.gray
                .ignoresSafeArea()

            Rectangle()
                .foregroundColor(.white)
                .frame(width: 250,
                       height: 250)
        }
        
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

f:id:tokizuoh:20220226122314p:plain

Rectangleは縦横比が1:1になっていて、View Hierarchyで見ても縦横それぞれ250ptになっている。
ということはTextFieldの用途としてheight可変は考慮されていない?

そもそもTextFieldの用途あってる?

When you need to collect text input from the user, use an appropriate text input view, like TextField or TextEditor.
https://developer.apple.com/documentation/swiftui/text-input-and-output

おや、TextEditorなるものがあるらしい。

TextEditor

A text editor view allows you to display and edit multiline, scrollable text in your app’s user interface.
https://developer.apple.com/documentation/swiftui/texteditor

複数行に渡る入力を受け付けたい時はTextFieldではなくTextEditorを使ったほうが良さそう。

import SwiftUI

struct ContentView: View {
    
    @State private var text: String = ""
    
    var body: some View {
        ZStack(alignment: .center) {
            Color.gray
                .ignoresSafeArea()

            TextEditor(text: $text)
                .frame(width: 250,
                       height: 250)
        }
        
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

f:id:tokizuoh:20220226135538p:plain

あっさり目的を叶えられた。
iOS14以降からの登場で知らなかった。

参考