我有一个用于 macOS 应用程序的简单 Swift 代码:
// ViewController.swift
import Cocoa
let string = "line 1\nline 2\nline 3\nline 4\nline 5\nline 6\nline 7\nline 8\nline 9\nline 10\nline 11\nline 12\nline 13\nline 14\nline 15\nline 16\nline 17\nline 18\nline 19\nline 20\nline 21\nline 22\nline 23\nline 24\nline 25\nline 26\nline 27\nline 28\nline 29\nline 30"
class ViewController: NSViewController {
private func setupTextView() {
let scrollView = NSTextView.scrollableTextView()
guard let textView = scrollView.documentView as? NSTextView else {
return
}
textView.string = string
/**
* If I comment the following line, it won't scroll.
*/
textView.layoutManager?.allowsNonContiguousLayout = true
view.addSubview(scrollView)
scrollView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
view.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
view.topAnchor.constraint(equalTo: scrollView.topAnchor),
view.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
view.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
])
}
override func viewDidLoad() {
super.viewDidLoad()
/**
* If I execute self.setupTextView() directly without DispatchQueue.main.async, it won't scroll.
*/
DispatchQueue.main.async {
self.setupTextView()
}
}
}
当应用程序启动时,文本视图自动滚动到底部,这与我希望它保持不滚动以便第一行可见的意图相反。
有趣的是,如果我注释掉
textView.layoutManager?.allowsNonContiguousLayout = true
,或者将 self.setupTextView()
移出异步块,它就会按预期工作。
只是想了解滚动的根本原因是什么,以及避免滚动的最佳实践是什么(假设我需要将其设置为异步并且需要
allowsNonContiguousLayout
)?
scrollView.frame.size
是(width = 0, height = 0)
。无法正确计算行数和滚动位置。当稍后调整滚动视图大小时,滚动位置仍然不正确。
我认为非连续布局计算行数的方式不同。
异步块在其超级视图可见时添加滚动视图。我认为帧大小、行数和滚动位置是按不同顺序计算的。
解决方案:将滚动视图的帧大小设置为实际值。例如本例中
scrollView.frame = view.bounds
或
scrollView.frame.size = NSSize(width: 100, height: 100)