ios - 如何最好地优化 NSLayoutConstraint?

标签 ios swift uiview nslayoutconstraint custom-keyboard

各位同事,

我开发了一个自定义键盘。键盘类型(字母、数字、特殊字符)之间的切换速度存在问题。这是由于每次重新绘制按钮时的事实。 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
    }
    

我看到了两种优化变体:

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

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

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

最佳答案

在视频中我觉得速度相当快。

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

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

关于ios - 如何最好地优化 NSLayoutConstraint?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34323926/

相关文章:

ios - Branch.io:添加的元数据参数未获取路由:IOS Deep Link

uiview - BeginAnimations 和 CommitAnimations with NavigationController.PushViewController

ios - 通过 Storyboard将 UIPageControl 添加到 UIPageViewController

ios - 没有 GPS iOS 的室内路由

ios - 设备上的键盘扩展崩溃

ios - 固定在 UITableview 底部的 float 按钮,scrollViewDidScroll 无法正常工作

swift - 如何在 swift 2.2 中更改 pickerview 中的文本/字体大小?

ios5 - UIViewContentMode 模式指的是什么类型的内容?

ios - UIView 中的 UISegmentedControl 不响应更改事件

ios - Swift - 将图像添加到圆形 View