【问题标题】:How best to optimize NSLayoutConstraint?如何最好地优化 NSLayoutConstraint?
【发布时间】:2015-12-16 23:12:11
【问题描述】:

同事们,

我开发了一个自定义键盘。在键盘类型(字母、数字、特殊字符)之间切换的速度存在问题。这是因为每次按钮都会重新绘制。 NSLayoutConstraint 我设置如下:

  1. 有一个类 KeyboardViewController。他添加到他的 KeyboardView

        let left = NSLayoutConstraint(item: self.keyboardView, attribute: .Left, relatedBy: .Equal,
                toItem: self.view, attribute: .Left, multiplier: 1.0, constant: 0.0)
            let top = NSLayoutConstraint(item: self.keyboardView, attribute: .Top, relatedBy: .Equal,
                toItem: placeForSuggestion!, attribute: .Bottom, multiplier: 1.0, constant: 0.0)
            let right = NSLayoutConstraint(item: self.keyboardView, attribute: .Right, relatedBy: .Equal,
                toItem: self.view, attribute: .Right, multiplier: 1.0, constant: 0.0)
            let bottom = NSLayoutConstraint(item: self.keyboardView, attribute: .Bottom, relatedBy: .Equal,
                toItem: self.view, attribute: .Bottom, multiplier: 1.0, constant: 0.0)
            let height = NSLayoutConstraint(item: self.keyboardView, attribute: .Height, relatedBy: .Equal,
                toItem: self.view, attribute: .Height, multiplier: 1.0, constant: 216)
            left.priority = 999
            right.priority = 999
            bottom.priority = 999
            top.priority = 999
            height.priority = 999
            self.view.addConstraints([left, right, top, bottom, height])
    
  2. 在KeyboardView类中,按钮添加如下:

    super.updateConstraints()
    
    if !layoutConstrained {
    
        var lastRowView: UIView? = nil
        for (rowIndex, keyRow) in keyRows.enumerate() {
            var lastKeyView: UIView? = nil
            for (keyIndex, key) in keyRow.enumerate() {
    
                var relativeWidth: CGFloat = 0.0;
                switch key.type! {
                case .ModeChange:
                    relativeWidth = 0.92/8
                case .KeyboardChange:
                    relativeWidth = 0.92/8
                case .Space:
                    relativeWidth = 3.92/8
                case .Return:
                    relativeWidth = 1.84/8
                default:
                    relativeWidth = 0.0
                }
    
                key.translatesAutoresizingMaskIntoConstraints = false
    
                if let lastView = lastKeyView {
                    let left: NSLayoutConstraint!
                    if (key.keyCap == "Z" || (key.keyCap == "backspace" && keyRow[keyIndex - 1].keyCap == "M")) {
                        left = NSLayoutConstraint(item: key, attribute: .Left, relatedBy: .Equal,
                            toItem: lastView, attribute: .Right, multiplier: 1.0, constant: englishMZSpace)
                    } else {
                        left = NSLayoutConstraint(item: key, attribute: .Left, relatedBy: .Equal,
                            toItem: lastView, attribute: .Right, multiplier: 1.0, constant: distanceBetweenKeys)
                    }
                    let top = NSLayoutConstraint(item: key, attribute: .Top, relatedBy: .Equal,
                        toItem: lastView, attribute: .Top, multiplier: 1.0, constant: 0.0)
                    let bottom = NSLayoutConstraint(item: key, attribute: .Bottom, relatedBy: .Equal,
                        toItem: lastView, attribute: .Bottom, multiplier: 1.0, constant: 0.0)
                    var width: NSLayoutConstraint?
                    if relativeWidth == 0.0 {
                        width = NSLayoutConstraint(item: key, attribute: .Width, relatedBy: .Equal,
                            toItem: lastView, attribute: .Width, multiplier: 1.0, constant: 0.0)
                    } else {
                        width = NSLayoutConstraint(item: key, attribute: .Width, relatedBy: .Equal,
                            toItem: self, attribute: .Width, multiplier: relativeWidth, constant: 0.0)
                    }
                    self.addConstraints([left, top, bottom, width!])
                } else {
                    let leftEdge: NSLayoutConstraint
                    if key.keyCap == "A" {
                        leftEdge = NSLayoutConstraint(item: key, attribute: .Left, relatedBy: .Equal,
                            toItem: self, attribute: .Left, multiplier: 1.0, constant: englishALSpace)
                    } else {
                        leftEdge = NSLayoutConstraint(item: key, attribute: .Left, relatedBy: .Equal,
                            toItem: self, attribute: .Left, multiplier: 1.0, constant: leftRightSpace)
                    }
    
                    self.addConstraint(leftEdge)
    
                    if let lastRow = lastRowView {
                        let top = NSLayoutConstraint(item: key, attribute: .Top, relatedBy:.Equal,
                            toItem: lastRow, attribute: .Bottom, multiplier: 1.0, constant: rowTopInset)
                        let height = NSLayoutConstraint(item: key, attribute: .Height, relatedBy: .Equal,
                            toItem: lastRow, attribute: .Height, multiplier: 1.0, constant: 0.0)
    
                        self.addConstraints([top, height])
                    } else {
                        let topEdge =  NSLayoutConstraint(item: key, attribute: .Top, relatedBy:.Equal,
                            toItem: self, attribute: .Top, multiplier: 1.0, constant: rowTopInset)
    
                        self.addConstraint(topEdge)
                    }
    
                    if rowIndex == keyRows.count - 1 {
                        let bottomEdge = NSLayoutConstraint(item: key, attribute: .Bottom, relatedBy: .Equal,
                            toItem: self, attribute: .Bottom, multiplier: 1.0, constant: -rowBottomInset)
                        self.addConstraint(bottomEdge)
                    }
    
                    lastRowView = key
                }
    
                if keyIndex == keyRow.count - 1 {
                    let rightEdge: NSLayoutConstraint
                    if key.keyCap == "L" {
                        rightEdge = NSLayoutConstraint(item: key, attribute: .Right, relatedBy: .Equal,
                            toItem: self, attribute: .Right, multiplier: 1.0, constant: -englishALSpace)
                    } else {
                        rightEdge = NSLayoutConstraint(item: key, attribute: .Right, relatedBy: .Equal,
                            toItem: self, attribute: .Right, multiplier: 1.0, constant: -leftRightSpace)
                    }
                    self.addConstraint(rightEdge)
                }
    
                lastKeyView = key
            }
        }
        layoutConstrained = true
    }
    

我看到了 2 种优化变体:

  1. 第一次运行后缓存所有的NSLayoutConstraint
  2. 使用 CGRectMake 代替 NSLayoutConstraint

您或许可以提供更多相关选项?

在本视频中,我尝试切换键盘并快速打印https://yadi.sk/i/36YxEwgtmHJVd

【问题讨论】:

    标签: ios swift uiview nslayoutconstraint custom-keyboard


    【解决方案1】:

    在视频中对我来说似乎很快。

    但是,我建议不要每次都重新创建布局约束,而是为每种键盘类型创建一次,然后在现有键盘之间切换。关于不应该是内存问题的小视图,这比一直重新创建和删除约束要好得多。

    或者,如果关键数量保持(几乎)相同,您可以只更改约束的值,甚至为关键位置的变化设置动画以获得可能不错的效果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-06
      • 2012-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-08
      相关资源
      最近更新 更多