嵌套相对宽度的自动布局性能?

时间:2015-10-18 01:06:38

标签: macos swift performance cocoa autolayout

总结一下我的问题:当我有很多子视图,其宽度等于其父级的宽度,其中父级的宽度等于其父级的宽度时,会有很大的性能影响。窗口水平调整大小。

我正在从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的宽度时。如果我只是将其设置为常量,则不会出现真正的性能下降。

我的视图层次结构设置不正确,还是我忽略了导致此性能问题的某些内容?

1 个答案:

答案 0 :(得分:2)

我同意肯,你正在重新发明表格视图(及其所有相关的优化)。有没有使用表视图或集合视图的最重要原因?

性能提升是因为在水平调整大小时,您需要重新计算每个子视图的大小!不只是那些可见的。

如果你必须这样做的话。一些优化尝试将是:

  • 不使用宽度,而是将前缘和后缘绑定到superview。
  • 不要将所有子视图绑定到superview。仅将第一个绑定到superview,将所有其他绑定到第一个视图。
  • 重复表/集合视图策略,仅更新可见视图的常量。 (当你可以使用其中一种时,这会有点愚蠢!)

我还注意到您现在正在修复评论视图的高度。一旦启用flex,性能就会受到影响,因为视图必须实时调整两个维度,影响页面下面的所有视图。

TL; DR - 为自己省去很多麻烦。使用表格或集合视图。