This article has participated in the call for good writing activity, click to view:Back end, big front end double track submission, 20,000 yuan prize pool waiting for you to challenge!
This article is based on a question posed at the June event:
Along the digging friends of the point, a language wake up dreamers.
IOS controls layout dependencies
The iOS UI layout has always been unique. If you have tried the front-end CSS, the UI writing of Flutter, or even the Android LAYOUT via XML, you will find that the iOS layout thinking is completely irrelevant to the above ones.
My personal favorite UI layout is pure code layout, and I’ve compiled some of its uses in Swift: The Layout Library — SnapKit.
UI layouts written with SnapKit are built on dependencies between controls.
It can be said that the UI layout of the same page is written using SnapKit, which may be coded differently by different programmers — depending on different results.
Depending on the dependencies of the controls, the layout is written subtly differently, which in turn affects the layout of more components.
Ok, let’s start with a simple example.
Simple button layout
The use of updateConstraints
Let’s start with a snippet of code and illustrate it with a Gif operation:
import UIKit import SnapKit import RxCocoa class SnapKitLayoutController: BaseViewController { override func viewDidLoad() { super.viewDidLoad() setupUI() } private func setupUI() { title = Let redButton = UIButton(type: UIButton) .custom) redButton.backgroundColor = .red view.addSubview(redButton) redButton.snp.makeConstraints { (make) in make.top.equalTo(view).offset(100) make.leading.equalTo(view).offset(16) make.trailing.equalTo(view).offset(-16) Make. Height. EqualTo (44)} / / / button click event, updated layout redButton. Rx. Tap. The subscribe {[weak self. Let self = self, let self = self, Let redButton = redButton else {return} / / / note used here is the update redButton. SNP. UpdateConstraints {(make) in make.top.equalTo(self.view).offset(200) } }.disposed(by: rx.disposeBag) let blueButton = UIButton(type: . The custom) blueButton. BackgroundColor =. Blue the addSubview (blueButton) / / / blue layout is completely dependent on redButton blueButton.snp.makeConstraints { (make) in make.top.equalTo(redButton.snp.bottom).offset(10) make.leading.trailing.height.equalTo(redButton) } } }Copy the code
The above code does two things:
-
Generate child control redButton and blueButton, wherein the layout of blueButton is completely dependent on redButton.
-
RedButton has a button click event that changes the top value of redButton relative to the top value of view.
Here, let’s look at the effect:
RedButton is offset downward, from 100 to 200 via updateConstraints.
Since blueButton relies on the bottom of redButton, its bottom relative to redButton is always 10, so blueButton moves relative to redButton.
We can refine the click events of the redButton so that not only top but also leading and trailing changes after the click.
Key code:
/ / / button click event, updated layout redButton. Rx. Tap. The subscribe {[weak self. Let self = self, let self = self, Let redButton = redButton else {return} / / / note used here is the update redButton. SNP. UpdateConstraints {(make) in make.top.equalTo(self.view).offset(200) make.leading.equalTo(self.view).offset(50) make.trailing.equalTo(self.view).offset(-50) } }.disposed(by: rx.disposeBag)Copy the code
Click the result:
RedButton’s top, leading, and trailing values all change accordingly, because blueButton’s layout is completely dependent on redButton.
At the end of this section let’s take a look at SnapKit’s documentation for updateConstraints:
Note the red: update only the value of constant. What does that mean?
In this code, redButton’s dependency on the controller’s self.view — top, leading, and trailing — does not change. Only the value in the function offset(value) after equalTo(self.view) is changed.
That’s what Digg answered when I asked — the constant value of the update constraint.
The use of remakeConstraints
With the previous updateConstraints explanation, the description for remakeConstraints is now much simpler. Let’s start with the official document:
RemakeConstraints is much like makeConstraints except that this is held to remove the previous layout dependency before making, and then to reframe it.
Simply put: cut the heavy chain.
UpdateConstraints => updateConstraints=> updateConstraints=> updateConstraints=> updateConstraints
/ / / button click event, updated layout redButton. Rx. Tap. The subscribe {[weak self. Let self = self, let self = self, Let redButton = redButton else {return} / / / note used here is the update redButton. SNP. RemakeConstraints {(make) in make.top.equalTo(self.view).offset(200) make.leading.equalTo(self.view).offset(50) make.trailing.equalTo(self.view).offset(-50) } }.disposed(by: rx.disposeBag)Copy the code
Click the result:
Does it feel like using updateConstraints?
Remember that the redButton is reworked with top, leading, and trailing, but with the height parameter not reworked.
We can look at the initial code:
redButton.snp.makeConstraints { (make) in
make.top.equalTo(view).offset(100)
make.leading.equalTo(view).offset(16)
make.trailing.equalTo(view).offset(-16)
make.height.equalTo(44)
}
Copy the code
So if you look closely at the rendering of the call to remakeConstraints, you will see that the button is no longer 44 in height. I also verified this with layers:
As the layout setting with height of 44 was removed and was not set again when using remakeConstraints, the system placed us with 34, which I have not quite figured out.
However, this example verifies the effectiveness of remakeConstraints.
If you want to keep the height of the button in place after using remakeConstraints, add this to the closure of make.height.equalto (44) to cut out the height layout and place it again.
UpdateConstraints vs. remakeConstraints
-
UpdateConstraints does not change previous controls’ dependencies on other controls; it simply updates the values of other controls’ dependencies.
-
RemakeConstraints simply removes all previous dependencies from other controls and then builds new ones.
In view of the above description, I personally feel that updateConstraints is superior to remakeConstraints in terms of performance, and that remakeConstraints needs to be aware of all the dependencies that are immutable when it comes to rebuilding and should be rewritten as well.
Where updateConstraints is used, you can build with remakeConstraints, and vice versa.
conclusion
SnapKit has been around for so long that we’re always hoping that the UI layout won’t change overnight.
While business is not necessarily wishful thinking, using updateConstraints and remakeConstraints while using SnapKit makes it a little easier to animate the UI layout.
I’ve also been between updateConstraints and remakeConstraints for too long and I wouldn’t have gone any further if I hadn’t been reminded by a friend, although it’s to my credit that I’m cheeky enough to ask this question.
No, reading more official documents is the fastest and most direct way to find the answer, and I also firmly remember and continue to practice.
For a further example of updateConstraints and remakeConstraints, look at the infoViewCell. swift file in my open source project WanAndroid client, which contains two different cells. Implement layout changes in updateConstraints and remakeConstraints respectively to achieve the same functionality.
The WanAndroid client written by RxSwift is now open source
Currently RxSwift written wanAndroid client has been open source –Project link. Remember to give a star!
Attached is an effect picture: