title: How best to optimize NSLayoutConstraint?
body: <p>Colleagues,</p>
  
  <p>I develop a custom keyboard. There was a problem with the speed of switching between types of keyboards (letters, numbers, special characters). This is due to the fact that each time the button is re-drawn. NSLayoutConstraint I set up as follows:</p>
  
  <ol>
  <li><p>There is a class KeyboardViewController. He adds to his KeyboardView</p>
  
  <pre><code>    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])
  </code></pre></li>
  <li><p>In the class KeyboardView, buttons are added as follows:</p>
  
  <pre><code>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" &amp;&amp; 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
  }
  </code></pre></li>
  </ol>
  
  <p>I see 2 variants of optimization:</p>
  
  <ol>
  <li>After the first run to cache all NSLayoutConstraint</li>
  <li>Use CGRectMake instead NSLayoutConstraint</li>
  </ol>
  
  <p>You may be able to offer more relevant options?</p>
  
  <p>In this video I try to switch keyboard and print quickly <a href="https://yadi.sk/i/36YxEwgtmHJVd" rel="nofollow">https://yadi.sk/i/36YxEwgtmHJVd</a></p>