macOSアプリを開発する中でNSTextViewを使っているにも関わらず、(テキストが表示領域より多くなっても)スクロールできない問題に悩まされたので、その解決法を紹介します。
問題
コードでNSTextViewを生成&追加するとき、以下のようにするとテキストが下端まで行ってもスクロールすることができません。
// スクロールできないTextViewの例
class ViewController: NSViewController {
private let textView = NSTextView()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(textView)
// ウィンドウいっぱいにTextViewを設置
textView.translatesAutoresizingMaskIntoConstraints = false
textView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
textView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
textView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
textView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
}
}
解法
スクロールできるNSTextViewを生成するためには、NSTextView.scrollableTextView()
メソッドを使い、以下のように実装するとうまくいきます。
// スクロールできるTextViewの例
class ViewController: NSViewController {
private let scrollView = NSTextView.scrollableTextView()
private lazy var textView: NSTextView = {
let view = scrollView.documentView as! NSTextView
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(scrollView)
// ウィンドウいっぱいにTextViewを設置
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
}
}
NSTextViewを継承したクラスの場合
NSTextViewを継承したカスタムTextViewの場合でも、同様にscrollableTextView()
メソッドを使用することでtextView
オブジェクトを取り出して扱えます。
// カスタムTextView
class MyTextView: NSTextView {
...
}
class ViewController: NSViewController {
private let scrollView = MyTextView.scrollableTextView()
private lazy var textView: MyTextView = {
let view = scrollView.documentView as! MyTextView
return view
}()
...
}