It is very important to use the above three methods correctly for view layout in iOS. Here is an in-depth explanation of the functions and differences of these three methods.

Before we begin, explain one word: update cycle.

The update cycle, the process of updating the current screen view, begins when the current run loop ends.

setNeedsLayout()

Call this method: that is, tell the App to lay out and redraw the current view and its subviews during the update cycle.

This method is an asynchronous operation and must be called in the main thread. It returns immediately after being called. Because you don’t know when the update cycle will start, calling this method doesn’t give you precise control over when the view constraints updates. But because this approach can update multiple layout updates in a single update cycle, it performs better.

layoutIfNeeded()

Call this method: that is, tell the App to layout and redraw the current view and its subviews immediately, without waiting for an update cycle.

This method is a synchronous operation, and layout updates and view redraws are all updated before the method call completes.

layoutSubviews()

This method determines the location and size of the subview based on the constraints you set.

You can override this method when the subview performs a more elaborate layout. This method should be overridden only if the autoresizing and constrant-based behavior of the subview does not provide the desired behavior.

Do not call this method directly. If you want to force a layout update, call setNeedsLayout(). If you want to update the layout immediately, call layoutIfNeeded().

application

  • See my article for more details – How iOS animates Constraints
  • Full text/Fold up – Dynamically changing the height of the UITableViewCell
Func tableView(_ tableView: UITableView, cellForRowAt indexPath:) func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {// 1.1 cell configuration XXXXX // 1.2 Call layoutIfNeeded() cell.layoutifneeded ()returnCell} // 2. Change the corresponding constraints. Const = 100 // 3. Reload the corresponding cell @objc PrivatebuttonAction() {
    tableView.reloadRows(at: [xxIndexPath], with: .automatic)   
}
Copy the code

Best practices for constraining change

Apple Document: It is almost always cleaner and easier to update a constraint immediately after the affecting change has occurred. Deferring these changes to a later method makes the code more complex and harder to understand.

The Apple documentation recommends that it is the easiest and most straightforward way to modify constraints immediately when they change. For example, when a constraint needs to be updated in a button click event:

@IBAction func buttonAction(_ sender: UIButton) {
    animationChange()
}
 
private func animationChange() {/ / when the need to change, first change constraints heightConstraint. Constant = 300 / / in processing according to the demand response logic UIView. The animate (withDuration: 2.0) {self.view.layoutifneeded ()}}Copy the code

conclusion

  • LayoutSubviews () : Do not call this method directly. You can override this method in a subclass to get a finer layout of the subviews.
  • LayoutIfNeeded () : Synchronizes, updates and redraws current and subviews immediately without waiting for an update cycle.
  • SetNeedsLayout () : Asynchronously, updating the layout in the update cycle for better performance.

reference

  • medium
  • so