我有一个简单的macOS应用程序的Swift代码:
// ViewController.swift
import Cocoa
let string = (1...30).map { "line \($0)" }.joined(separator: "\n")
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()
移出xmlc块,它会像预期的那样工作。
只是想了解滚动的根本原因是什么,以及避免它的最佳实践是什么(考虑到我需要设置它,需要allowsNonContiguousLayout
)?
3条答案
按热度按时间nbewdwxp1#
您可以将
allowsNonContiguousLayout
放入一个专用的异步块中,以防止不必要的滚动,而无需将其注解掉:字符串
代码的其余部分将是相同的。
chy5wohz2#
scrollView.frame.size
是(width = 0, height = 0)
。行数和滚动位置无法正确计算。当滚动视图稍后调整大小时,滚动位置仍然不正确。我认为非连续布局计算行数的方式不同。
当它的超级视图可见的时候,这个块会添加滚动视图。我认为框架大小,行数和滚动位置是以不同的顺序计算的。
解决方案:将滚动视图的帧大小设置为实际值。
scrollView.frame = view.bounds
个或
scrollView.frame.size = NSSize(width: 100, height: 100)
个9udxz4iz3#
让我试试。为了避免这个问题,你可以修改设置,在文本视图布局之前设置allowsNonContiguousLayout属性。尝试同步设置文本视图和配置其属性,而不依赖于DispatchView.main.jsp。像这样。
字符串
通过同步设置文本视图,allowsNonContiguousLayout属性将在布局过程开始之前应用,从而有望防止意外的滚动行为。