14
8

More than 3 years have passed since last update.

SwiftUIでTextViewを使う(日本語入力可能)

Last updated at Posted at 2019-11-18

SwiftUIでTextViewを使うを参考にした。

import SwiftUI
import PlaygroundSupport

struct MultilineField: UIViewRepresentable {
    @Binding var text: String

    let onEditingChanged: (Bool) -> Void

    init(text: Binding<String>, onEditingChanged: @escaping (Bool) -> Void = {_ in}) {
        self._text = text
        self.onEditingChanged = onEditingChanged
    }

    func makeCoordinator() -> MultilineFieldCoordinator {
        MultilineFieldCoordinator(target: self, onEditingChanged: onEditingChanged)
    }

    func makeUIView(context: Context) -> UITextView {
        let textView = UITextView()
        textView.delegate = context.coordinator
        textView.text = text
        return textView
    }

    func updateUIView(_ textView: UITextView, context: Context) {
        if textView.text != text {
            textView.text = text
        }
    }
}

class MultilineFieldCoordinator : NSObject, UITextViewDelegate {
    let target: MultilineField
    let onEditingChanged: (Bool) -> Void

    init(target: MultilineField, onEditingChanged: @escaping (Bool) -> Void = {_ in}) {
        self.target = target
        self.onEditingChanged = onEditingChanged
    }

    func textViewDidChange(_ textView: UITextView) {
        target.text = textView.text
    }

    func textViewDidBeginEditing(_ textView: UITextView) {
        onEditingChanged(true)
    }

    func textViewDidEndEditing(_ textView: UITextView) {
        onEditingChanged(false)
    }
}

struct ContentView: View {
    @State var content = ""

    var body: some View {
        VStack {
            MultilineField(text: $content, onEditingChanged: update)
                .overlay(RoundedRectangle(cornerRadius: 5).stroke(Color(#colorLiteral(red: 0.803921568627451, green: 0.803921568627451, blue: 0.803921568627451, alpha: 1.0))))
                .padding()
            Text(content)
        }
    }

    func update(changed: Bool) {
        guard !changed else { return }
        //document.content = content
        //document.updateChangeCount(.done)
    }
}

PlaygroundPage.current.setLiveView(ContentView(content: """
千早ぶる神代もきかず龍田川
からくれなゐに水くくるとは
"""))

しかし、これだとSwiftUI側の入力値更新がリアルタイムに反映されない問題がある。例えばマークダウンのコードをリアルタイムでプレビューしたい時には、それを考慮して別の実装が必要。

リアルタイムで反映できるように修正した。

追記:Stateへの代入で更新されないのを修正した。

14
8
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
8