Чтобы подвести итог моей проблеме: когда у меня есть много дочерних представлений с шириной, равной ширине их родительского элемента, где ширина родителя равна ширине их родителя, при горизонтальном изменении размера окна происходит огромное увеличение производительности.Производительность автоматического макета с вложенными относительными ширинами?
Я извлечение большого количества комментариев от API и решил создать индивидуальный NSView
для каждого комментария, а затем вертикально пространством их всех в пределах NSScrollView
. Каждый отдельный комментарий увеличивается до высоты текста комментария и соответствует ширине контейнера. Это отлично работает, когда не так много загруженных комментариев, но когда комментарии обычно превышают 100, происходит огромное увеличение производительности при горизонтальном изменении размера окна.
Я создаю каждый комментарий Высказаться:
var lastComment:NSView = documentView // The last view to vertically position around
for (index, comment) in commentsArray.enumerate() {
var data = comment
data["attributedString"] = attributedString
let commentView = NSCommentView(data: data)
documentView.addSubview(commentView)
let verticalSpacing = (index == 0) ? 0 : 10 // Position the first comment without any top spacing
let secondAttribute = (index == 0) ? NSLayoutAttribute.Top : NSLayoutAttribute.Bottom
let widthConstraint = NSLayoutConstraint(item: commentView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: documentView, attribute: NSLayoutAttribute.Width, multiplier: 1, constant: 0)
let topConstraint = NSLayoutConstraint(item: commentView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: lastComment, attribute: secondAttribute, multiplier: 1, constant: verticalSpacing)
documentView.addConstraints([widthConstraint, topConstraint])
lastComment = commentView
if index == commentsArray.count - 1{
let bottom = NSLayoutConstraint(item: commentView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: documentView, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 0)
documentView.addConstraint(bottom)
}
}
Где NSCommentView
определяется как:
class NSCommentView: NSView {
func setupFrame(){
self.wantsLayer = true
self.translatesAutoresizingMaskIntoConstraints = false
self.layer?.backgroundColor = NSColor.redColor().CGColor
// Set height of comment, fixed for testing
let heightConstraint = NSLayoutConstraint(item: self, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 50)
self.addConstraint(heightConstraint)
}
func setupTextView(attributedString: NSAttributedString){
let textView = NSTextView()
textView.translatesAutoresizingMaskIntoConstraints = false
textView.verticallyResizable = true
textView.textStorage?.setAttributedString(attributedString)
self.addSubview(textView)
let heightConstraint = NSLayoutConstraint(item: textView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 50)
textView.addConstraint(heightConstraint)
// The performance hit occurs when I set a width equal to the parent width:
let widthConstraint = NSLayoutConstraint(item: textView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: self, attribute: NSLayoutAttribute.Width, multiplier: 1, constant: 0)
self.addConstraint(widthConstraint)
}
convenience init(data:[String: AnyObject?]){
self.init()
setupFrame()
if data["isComment"] as! Bool {
let attributedString = data["attributedString"] as! NSAttributedString
setupTextView(attributedString)
}
}
}
Как вы можете видеть из кода, вопрос когда я пытаюсь установить ширину от NSTextView
до ширины NSCommentView
. Если я просто устанавливаю его как константу, то нет реальной деградации производительности.
Неправильно настроена ли моя иерархия взглядов, или я не замечаю того, что вызывает эту проблему производительности?
Кажется, что вы изобретаете табличный вид. Хорошей особенностью «NSTableView's», основанной на представлении, является то, что она удаляет представления для ячеек вне экрана. Это позволит ограничить общее количество и сохранить отзывчивость. Вам нужно будет профилировать с помощью инструментов, чтобы знать наверняка, но я подозреваю, что проблема заключается в том, что все ваши текстовые представления переставляют свой текст для новой ширины.Те, которые прокручиваются за кадром, не знают, что им не нужно это делать, по крайней мере, не сразу. Другие эксперименты: используйте пустую строку для всех текстовых просмотров; установите для параметра textView.textContainer.widthTracksTextView' значение false. –
О, и не используйте префикс 'NS' для ваших собственных классов. Это зарезервировано для классов Cocoa. –
@KenThomases спасибо за отзыв, я изменю свое соглашение об именах. Могу ли я настроить NSTableView с пользовательскими представлениями? Часть моей причины для выбора вида прокрутки состояла в том, что я решил, что должен использовать традиционный макет текста/столбца ... – Charlie