実現したいこと
SwiftUIでmacOSの日記アプリを作っていて、SwiftUI標準のTextEditorでは機能が足りないのでNSTextViewをNSViewRepresentableでラップして使おうとしました。NSTextViewがViewを埋め尽くしてくれるのが理想です。
下のコードが最低限の実装です。
Swift
1import SwiftUI 2import AppKit 3 4struct TextView: NSViewRepresentable { 5 @Binding var text: String 6 7 func makeNSView(context: Context) -> NSTextView { 8 let nsTextView = NSTextView() 9 nsTextView.delegate = context.coordinator 10 nsTextView.string = self.text 11 return nsTextView 12 } 13 14 func updateNSView(_ nsTextView: NSTextView, context: Context) { 15 nsTextView.string = self.text 16 } 17 18 func makeCoordinator() -> Coordinator { 19 Coordinator(self) 20 } 21} 22 23extension TextView { 24 class Coordinator: NSObject, NSTextViewDelegate { 25 var parent: TextView 26 27 init(_ parent: TextView) { 28 self.parent = parent 29 } 30 31 func textDidChange(_ notification: Notification) { 32 guard let nsTextView = notification.object as? NSTextView else { return } 33 self.parent.text = nsTextView.string 34 } 35 } 36} 37 38//MARK: - プレビュー 39struct TextView_Previews: PreviewProvider { 40 static var previews: some View { 41 TextView(text: .constant("サンプルテキスト\nサンプルテキスト\nサンプルテキスト\nサンプルテキスト\nサンプルテキスト\nサンプルテキスト")) 42 .frame(width: 600, height: 600, alignment: .center) 43 .border(Color.green) 44 .padding() 45 .previewDisplayName("TextView") 46 } 47}
これでテキストの編集は問題なくできるのですが、画像のようにNSTextViewがSwiftUIのViewの端まで広がらず、高さが合いません。
#やってみたこと
- makeNSView、updateNSViewメゾットの中に
nsTextView.frame = .init(x: 0, y: 0, width: 400, height: 300)
を入れて直接サイズを変えてみようとしました。この方法でwidthは変わりましたがheightを伸ばすことはできませんでした。 - 制約を使えばいいのかな、と考えて、空のNSViewにnsTextViewをaddSubView()で入れて、
NSLayoutConstraint.activate()
で4つの角を合わせました。この方法ではそもそもNSTextView自体が表示されませんでした。 - XcodeのデバッグツールでViewの階層構造を確認しました。緑の枠の中でグレーになっている部分はNSTextViewの一部ではないことを確認しました。
- Googleで「Swift UITextView UIViewRepresentable」や「Swift UIViewRepresentable size」で検索をかけました。(「NS」ではなく「UI」にしているのは、UIKitの方が情報が多いからです。基本的に違いはありません。)何時間か漁りましたが、目当てのものは(下記を除いて)見つかりませんでした。
- GitHubにMacEditorTextViewというコードがあるのを見つけました。これはちゃんと表示されますが、スクロール機能がついてしまっています。
これまで何度もSwiftUIでNSTextViewを使おうと試みてきましたが、この問題がどうしても解けません。どなたかご教示していただけないでしょうか。何か記述不足があればご指摘ください。
よろしくお願い致します。
#環境
macOS 11.1
Xcode 12.3
Swift 5.3
あなたの回答
tips
プレビュー