1, What’s Auto Layout
Auto Layout is a library provided by Apple’s UIKit framework for dynamically calculating the size and position of UIViews and their subclasses.
Speaking of Auto Layout, we have to say Cassowary algorithm, because Auto Layout is built on the basis of Cassowary algorithm. In 1997, the Layout algorithm used by Auto Layout was published, which is called efficient linear equation solving algorithm. In 2011, Apple used the Cassowary algorithm to provide developers with an Auto Layout library. Due to the excellent Cassowary algorithm itself, not only apple, many developers have applied Cassowary algorithm in different development languages, such as JavaScript, ASP.NET, Java, C++, etc. There are libraries using Cassowary algorithm. It can also be seen from this that Cassowary’s algorithm is excellent and advanced, otherwise it would not be so widely used.
Apple introduced Auto Layout in iOS 6, but now that iOS 12 has been updated, many developers still don’t want to use Auto Layout. Mostly concerns about its anti-human syntax and performance issues.
In response to some of the problems with Auto Layout, Apple introduced NSLayoutAnchor with a cleaner syntax when iOS 9 was released. UIStackView, which mimics the layout ideas of the front Flexbox, was also released to provide developers with better options for automatic layout.
At apple,WWDC 2018 High Performance Auto LayoutAccording to Apple engineers, iOS 12 will significantly improve Auto Layout performance by allowing you to swipe to full frames. inWWDC 2018 What’s New in Cocoa TouchApple engineers talked about iOS 12’s Auto Layout improvements.As you can see from the picture,iOS 11
The number of nested views in view has increased exponentially in performanceiOS 12
The performance of a handwritten frame layout is basically similar.
From iOS 6 to iOS 12, Apple has been continuously improving The performance of Auto Layout and providing developers with simpler apis. If you still use Frame handwriting Layout, try Auto Layout. Here are a few common layout methods used on iOS.
2. Different versions of Auto Layout are used differently
If I wanted to create a View with a width and height of 120 and a center View, it would look like this:
1. Use frame handwriting for layout
UIView *centerView = [[UIView alloc] init];
centerView.backgroundColor = [UIColor redColor];
[self.view addSubview:centerView];
CGFloat width = self.view.frame.size.width;
CGFloat height = self.view.frame.size.height;
[centerView setFrame:CGRectMake(width / 2 - (60), height / 2 - (60), 120, 120)];
Copy the code
Add constraints to the NSLayoutConstraint syntax provided in iOS 6
centerView.translatesAutoresizingMaskIntoConstraints = NO; NSLayoutConstraint *consW = [NSLayoutConstraint constraintWithItem:centerView attribute:NSLayoutAttributeWidth RelatedBy: NSLayoutRelationEqual toItem: self. The view attribute: NSLayoutAttributeWidth multiplier: 0 constant: 120.0]; NSLayoutConstraint *consH = [NSLayoutConstraint constraintWithItem:centerView attribute:NSLayoutAttributeHeight RelatedBy: NSLayoutRelationEqual toItem: self. The view attribute: NSLayoutAttributeHeight multiplier: 0 constant: 120.0]; NSLayoutConstraint *consX = [NSLayoutConstraint constraintWithItem:centerView attribute:NSLayoutAttributeCenterX RelatedBy: NSLayoutRelationEqual toItem: self. The view attribute: NSLayoutAttributeCenterX multiplier: 1.0 constant: 0.0]; NSLayoutConstraint *consY = [NSLayoutConstraint constraintWithItem:centerView attribute:NSLayoutAttributeCenterY RelatedBy: NSLayoutRelationEqual toItem: self. The view attribute: NSLayoutAttributeCenterY multiplier: 1.0 constant: 0.0]; [self.view addConstraints:@[consW,consH,consX,consY]];Copy the code
3. Use VFL grammar
centerView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[centerView(120)]" options:0 metrics:nil views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"[centerView(120)]" options:0 metrics:nil views:views]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:centerView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:centerView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]];
Copy the code
4. Use third-party open source frameworksMasonryorSnapKit
__weak typeof (self) weakSelf = self;
[centerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(CGSizeMake(120, 120));
make.center.equalTo(weakSelf.view);
}];
Copy the code
let centerView:UIView = UIView.init()
view.addSubview(centerView)
centerView.backgroundColor = UIColor.red
centerView.snp.makeConstraints { (make) in
make.width.equalTo(120)
make.height.equalTo(120)
make.center.equalTo(view)
}
Copy the code
5. Provided by Apple after using iOS 9NSLayoutAnchor
let centerView:UIView = UIView.init()
view.addSubview(centerView)
centerView.backgroundColor = UIColor.red
centerView.translatesAutoresizingMaskIntoConstraints = false
centerView.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 0).isActive = true
centerView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: 0).isActive = true
centerView.widthAnchor.constraint(equalToConstant: 120).isActive = true
centerView.heightAnchor.constraint(equalToConstant: 120).isActive = true
Copy the code
Using the NSLayoutConstraint syntax and VFL syntax is the most complex, especially the NSLayoutConstraint syntax, which requires 30 + lines of code to achieve the same effect. The more lines of code you have, the more likely you are to get an error, which is one of the reasons why many developers don’t want to use Auto Layout (or the API provided by the system).
For apps compatible with iOS 9 and below, I suggest you post it. For apps compatible with iOS 9 and above, I suggest you post SnapKit or the NSLayoutAnchor API. After all, the library for navigation has not been updated for two years.
Here, I recommend the use of NSLayoutAnchor in preference. Third-party open source libraries are always confronted with some problems:
iOS
The adaptation and compatibility problems caused by the update of the system version, if it is open source code, apple will release the new version, and the author of the code will do the compatibility and adaptation- The author of the code stops updating the code, which makes it very passive for us developers to either modify the code ourselves or choose the newer open source code
- Using system libraries can reduce package size when packaging
3,
Auto Layout
Life cycle of
As mentioned above, Apple’s Auto Layout is based on Cassowary algorithm. On this basis, Apple provides a Layout Engine to manage the Layout of the page, to complete the creation, update, destruction and so on.
After the APP is started, a resident thread will be started to listen for the change of the constraint. When the constraint changes, it will Deffered Layout Pass(delayed Layout Pass) and perform fault tolerance processing (such as some views did not confirm or missing Layout declaration when updating the constraint). After completion, it will enter the state of constraint monitoring change.
The next time a view is refreshed (such as a call to layoutIfNeeded()), the Layout Engine calls layoutSubviews() from top to bottom and calculates the size and location of each subview through the Cassowary algorithm. Then copy the subview frame from the layout Engine, and the process is the same as drawing and rendering the frame by hand. Most of the work with Auto Layout and handwritten frames is in Layout calculations.
4,
NSLayoutAnchor
Commonly used attributes
- leadingAnchor
- trailingAnchor
- leftAnchor
- rightAnchor
- topAnchor
- bottomAnchor
- widthAnchor
- heightAnchor
- centerXAnchor
- centerYAnchor
- firstBaselineAnchor
- lastBaselineAnchor
For some common attributes of NSLayoutAnchor, its functions can be seen through its naming, which will not be described here. If you want to know more, please refer to Apple Developer NSLayoutAnchor.
5, Auto Layout several update constraint methods
-
SetNeedsLayout: Tells the page that it needs to be updated, but does not start updating immediately. LayoutSubviews is called immediately after execution.
-
LayoutIfNeeded: Notifies the page layout to be updated immediately. So it’s usually used with setNeedsLayout. You need to call this method if you want to generate a new frame immediately, so you can use this method to animate a general layout animation after updating the layout.
-
LayoutSubviews: Updates subview constraints
-
SetNeedsUpdateConstraints: need to be updated, but not immediately start
-
UpdateConstraintsIfNeeded: immediately update the constraints
-
UpdateConstraints: Updates the View constraints
6,
NSLayoutAnchor
Precautions for Use
1. In useNSLayoutAnchor
When adding constraints to a view, make sure that thetranslatesAutoresizingMaskIntoConstraints
Set up thefalse
centerView.translatesAutoresizingMaskIntoConstraints = false
Copy the code
2. In usesafeAreaLayoutGuide
adapteriPhone X
Wait for the right modeliOS 11
Previous system adaptation, otherwise it will lead to Crash on the lower version of the system
# if available (iOS 11.0. *) {tableView. TopAnchor. The constraint (equalTo: self. View. SafeAreaLayoutGuide. TopAnchor, constant: 0).isActive = true } else { tableView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 0).isActive = true }Copy the code
3. Activate the constraint after setting itisActive
fortrue
let centerX: NSLayoutConstraint = centerView.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 0)
centerX.isActive = true
Copy the code
4,leadingAnchor
Don’t get along withleftAnchor
A mixture of
centerView.leadingAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true
Copy the code
centerView.leftAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true
Copy the code
Error code: error code: error code: error code: error code: error code: error code
While the NSLayoutAnchor class provides additional type checking, it is still possible to create
invalid constraints. For example, the compiler allows you to constrain one view’s leadingAnchor
with another view’s leftAnchor, since they are both NSLayoutXAxisAnchor instances. However,
Auto Layout does not allow constraints that mix leading and trailing attributes with left or right
attributes. As a result, this constraint crashes at runtime.
Copy the code
Likewise, trailingAnchor and rightAnchor should not be used together.
5. How to refresh a constraint
For example, if I want to change the width of a UIView, I can add the UIView width to the class property, and then change the constant parameter where necessary, and then refresh the constraint, as follows:
var centerView: UIView!
var centerWidth: NSLayoutConstraint!
Copy the code
self.centerView = UIView.init()
view.addSubview(self.centerView)
self.centerView.backgroundColor = UIColor.red
self.centerView.translatesAutoresizingMaskIntoConstraints = false
self.centerView.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 0).isActive = true
self.centerView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: 0).isActive = true
self.centerWidth = self.centerView.widthAnchor.constraint(equalToConstant: 120)
self.centerWidth.isActive = true
self.centerView.heightAnchor.constraint(equalToConstant: 120).isActive = true
Copy the code
Self. CenterWidth. Constant = 250 weak var weakSelf = self UIView. The animate (withDuration: 0.35, animations: {weakSelf? .centerView.superview? .layoutIfNeeded() }) { (finished) in }Copy the code
The effect is as follows:
If it isxib
orstoryboard
“Then it’s even easier. Just press the keyboardcontrol
Key, drag it to the corresponding class, and then modify and refresh the constraints where necessary. The operation is as follows:
6, set the width to height ratio
During the development, we will meet some requirements to set constraints according to the aspect ratio of UIView. For example, in general, the aspect ratio of displaying videos is 16:9. Set the aspect ratio by code as follows:
centerView.heightAnchor.constraint(equalToConstant: 90).isActive = true
centerView.widthAnchor.constraint(equalTo: centerView.heightAnchor, multiplier: 16 / 9).isActive = true
Copy the code
7,
Auto Layout
The adaptiveUITableViewCell
High usage
1, use,rowHeight
Set the height
In general, if the height of each Cell of a UITableView is fixed we can specify a value, but if the height of the UITableView is not set, the system will default to the rowHeight height of 44.
tableview.rowHeight = 44;
Copy the code
You can also set the height of the UItableView via the UITableViewDelegate delegate.
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 50
}
Copy the code
If you manually calculate the height of each UItableViewCell, also implemented in this proxy, return the height of each UItableViewCell by calculating the height.
2, use,estimatedRowHeight
Set the height
UItableView inherited from UIScrollView, UIScrollView roll need to set up after the contentSize, then according to the bounds of oneself, contentInset, contentOffset property to compute the length of a scrollable. The UITableView does not know these parameters at initialization, but only after setting the delegate and dataSource can it calculate the scrollable length based on the number of uITableViewCells created and the height of the loaded UITableViewCell.
When using Auto Layout to adapt the height of the UITableViewCell, you should set an estimate in advance. The closer the estimate is to the true value, the better.
tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = 200
Copy the code
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 200
}
Copy the code
As shown above: This interface uses Auto Layout + estimatedRowHeight to complete the adaptive height. When adding constraints, the distance from the top (top) of each UIView to the bottom (bottom) of the previous view should be set according to the information from top to bottom. We also calculate the height of all the controls inside the UITableViewCell. The problem is that the height cannot be calculated before the details of the content posted by users are provided with data. Here, you can set a default height for the content text UILabel and let it automatically calculate the height according to the content filling:
topicInfoLab.heightAnchor.constraint(greaterThanOrEqualToConstant: 20).isActive = true;
topicInfoLab.font = UIFont.init(name: "Montserrat-SemiBold", size: 12)
topicInfoLab.numberOfLines = 0
Copy the code
If the user posts the content without an image, set the distance from the UILabel to the bottom of the UITableView constraint.
detailsLab.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -8).isActive = true
Copy the code
If the user posts with images, be sure to set the constraint distance from the bottom of the UItableViewCell to the last image after calculating the position and size of each image.
for(idx, obj) in imageArray.enumerated() { //..... To calculate the size of the picture and location if independence idx = = imageArray. {count - 1 / / set the last image distance constraint at the bottom of the photo. The bottomAnchor. The constraint (equalTo: self.contentView.bottomAnchor, constant: -8).isActive = true } }Copy the code
Implementation ideas as shown in the figure above, see the code for specific implementation
Eight,
Compression Resistance Priority
和Hugging Priority
use
Compression Resistance Priority and Hugging Priority tend to be used in conjunction in practical use, which respectively deal with the squeezing situation caused by too little and too much content among multiple views on a synonymous horizontal line.
Hugging Priority Means the Priority of self-wrapping, and the higher the Priority, the size will be padded according to the content of the control.
Compression Resistance Priority, which means cutting according to this Priority when there is not enough content to display. The lower the priority, the easier it is to cut.
ContentHuggingPriority |
Represents the currentUIView Content doesn’t want to be stretched |
---|---|
ContentCompressionResistancePriority |
Represents the currentUIView Content does not want to be shrunk |
By default:HuggingPriority = 250 |
By default:CompressionResistancePriority = 750 |
To set the stretching priority of 2 Uilabels, use code:
fristLab.setContentHuggingPriority(UILayoutPriority(rawValue: 251), for: .horizontal)
secondLab.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 750), for: .horizontal)
Copy the code
9,
This paper mainly shares several implementation methods and matters needing attention of Apple Auto Layout. Whether to use Auto Layout in actual development by pure code, XIB + code or Storyboard + code, Or xiB + Storyboard + code, depending on the requirements of the team, personal habits, and the complexity of the App. For the use of Auto Layout on the view, I recommend using Auto Layout for a simple UI or a single interface. For the operation or refreshing of a complex UI, I recommend using Frame + manual Layout.
This article demo, please stamp here
Links:
Analyze Auto Layout and new features of iOS versions
How does Auto Layout carry out automatic Layout and its performance?
Apple Developer High Performance Auto Layout
Apple Develope NSLayoutConstraint
WWDC 2018 What’s New in Cocoa Touch