2015-10-18 3 views
0

Чтобы подвести итог моей проблеме: когда у меня есть много дочерних представлений с шириной, равной ширине их родительского элемента, где ширина родителя равна ширине их родителя, при горизонтальном изменении размера окна происходит огромное увеличение производительности.Производительность автоматического макета с вложенными относительными ширинами?


Я извлечение большого количества комментариев от 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. Если я просто устанавливаю его как константу, то нет реальной деградации производительности.

Неправильно настроена ли моя иерархия взглядов, или я не замечаю того, что вызывает эту проблему производительности?

+0

Кажется, что вы изобретаете табличный вид. Хорошей особенностью «NSTableView's», основанной на представлении, является то, что она удаляет представления для ячеек вне экрана. Это позволит ограничить общее количество и сохранить отзывчивость. Вам нужно будет профилировать с помощью инструментов, чтобы знать наверняка, но я подозреваю, что проблема заключается в том, что все ваши текстовые представления переставляют свой текст для новой ширины.Те, которые прокручиваются за кадром, не знают, что им не нужно это делать, по крайней мере, не сразу. Другие эксперименты: используйте пустую строку для всех текстовых просмотров; установите для параметра textView.textContainer.widthTracksTextView' значение false. –

+0

О, и не используйте префикс 'NS' для ваших собственных классов. Это зарезервировано для классов Cocoa. –

+0

@KenThomases спасибо за отзыв, я изменю свое соглашение об именах. Могу ли я настроить NSTableView с пользовательскими представлениями? Часть моей причины для выбора вида прокрутки состояла в том, что я решил, что должен использовать традиционный макет текста/столбца ... – Charlie

ответ

1

Я согласен с Кеном, что вы повторно изобретаете табличный вид (и все связанные с ним оптимизации). Есть ли основная причина не использовать представление таблицы или коллекции?

Повреждение производительности связано с тем, что при изменении размера по горизонтали вы пересчитываете размер каждый подзаголовок! Не только те, которые видны.

Если вы должны сделать это таким образом. Некоторые попытки оптимизации были бы следующими:

  • Не использовать ширину, но привязывать передний и задний края к супервизу.
  • Не привязывайте все подзоны к супервизу. Привяжите только первое к супервизу, а все остальные - к первому виду.
  • Дублируйте стратегии таблицы/коллекции и обновляйте константы для видимых видов. (Это было бы глупо, хотя, когда вы могли бы просто использовать один из тех!)

Я также заметил, что вы фиксируя высоту взглядов комментарий прямо сейчас. После того, как вы включите эту функцию для гибки, производительность будет еще более страшной, так как представления будут иметь возможность изменять размер в двух измерениях, в реальном времени, влияя на все виды, находящиеся под ними на странице.

TL; DR - Спасите себе массу неприятностей. Используйте представление таблицы или коллекции.

+0

Не могли бы вы привести пример того, что я пытаюсь использовать в NSTableView? – Charlie

+0

Уверен - можете ли вы разместить изображение макета, или это просто строки текста? – Ben

+0

Конечно, http://i.imgur.com/XEmNf3Y.png Кроме того, я хотел сообщить вам, что я пробовал это, и дошел до создания пользовательского класса для представления комментариев, создания и назначения точек для конкретные части представления и внедрение 'numberOfRowsInTableView' и' objectValueForTableColumn', однако никаких данных на самом деле не видно, поэтому я прошу вас привести пример. – Charlie

Смежные вопросы