Why SwiftUI’s modifier order matters

Why SwiftUI’s modifier order matters

[[414805]]

This article is reprinted from the WeChat public account "Swift Community", written by Wei Xian Zhy. Please contact the Swift Community public account to reprint this article.

Whenever we apply a modifier to a SwiftUI view, we’re actually creating a new view with the changes applied — we’re not just modifying the existing view. If you think about it, this behavior makes sense — our views only retain the exact properties we give them, so if we set a background color or font size, there’s nowhere to store that data.

We'll look at why this happens in the next chapter, but first, I want to look at what this behavior actually means. Take a look at this code:

  1. Button( "Hello World" ) {
  2. // do nothing
  3. }
  4. .background(Color.red)
  5. .frame(width: 200, height: 200)

What do you think it will look like when it runs?

You've probably guessed wrong: you don't see a 200x200 red button with "Hello World" in the middle. Instead, you see a 200x200 empty square with "Hello World" in the middle and a red rectangle around "Hello World".

If you think about how modifiers work, you can see why this is the case: instead of setting properties on the view, each modifier creates a new struct with that modifier applied to it.

You can peek under the hood of SwiftUI by querying the type of the view body. Modify the button to look like this:

  1. Button( "Hello World" ) {
  2. print(type( of : self.body))
  3. }
  4. .background(Color.red)
  5. .frame(width: 200, height: 200)

Swift’s type(of:) method prints the exact type of a particular value, in this case it prints the following: ModifiedContent

You can see two things here:

  • Every time we modify a view, SwiftUI applies the modifier using the following generics: ModifiedContent
  • When we apply multiple modifiers, they are stacked together: ModifiedContent

To understand what the type is, start with the innermost type and work your way out:

  • The innermost type is ModifiedContent
  • On the outside, we have ModifiedContent<…, _FrameLayout> which takes our first view (button + background color) and gives it a Frame.

As you can see, we use a stack of ModifiedContent types - each view requires a view to transform and the actual changes to make, rather than modifying the view directly.

This means that the order of the modifiers is important. If we rewrite the code so that the background color is used after setting the Frame, then you get the expected result:

  1. Button( "Hello World" ) {
  2. print(type( of : self.body))
  3. }
  4. .frame(width: 200, height: 200)
  5. .background(Color.red)

Now the best way to think about it is, imagine that SwiftUI renders your view after every modifier. So any time you say .background(Color.red) it will change the background color to red regardless of what Frame you gave it. If you then expand the Frame afterwards it won't reload because the background has already been used.

Of course, this isn’t how SwiftUI actually works, because if it did it would be a performance nightmare, but it’s a neat mental shortcut you can use while learning.

An important side effect of using modifiers is that we can apply the same effect multiple times: each modifier simply adds to the previous content.

For example, SwiftUI provides us with the padding() modifier, which adds some space around a view so that it isn’t pushed against other views or the edge of the screen. If we apply padding, then a background color, then more padding and a different background color, we can give a view multiple borders, like this:

  1. Text( "Hello World" )
  2. .padding()
  3. .background(Color.red)
  4. .padding()
  5. .background(Color.blue)
  6. .padding()
  7. .background(Color.green)
  8. .padding()
  9. .background(Color.yellow)

Translated from Why modifier order matters[1]

References

[1]Why modifier order matters: https://www.hackingwithswift.com/books/ios-swiftui/why-modifier-order-matters

<<:  16 Must-Have Figma Plugins for UI/UX Designers

>>:  Android performance optimization - detailed explanation of memory management explosion caused by OOM crash

Recommend

Why did eBay return to China together with JD.com?

[[132426]] After a year of preparation, JD.com...

【APP Promotion Tips】Thoughts on Online Promotion

introduction: When I was setting the topic, I wan...

Oculus founder: Virtual reality is still 10 years away from you

In a recent interview with the Financial Times, O...

Is the information flow product-centric or user-centric?

In life, the things we come into contact with the...

Mobile Tool App Delivery Insight Report for the First Half of 2019

In the first half of 2019, mobile tool apps ranke...

Are mobile programmers having an easy time in 2017?

2016 was undoubtedly a year of anxiety and confus...

DingDong speakers tell you: "Intelligence" and "Quality" should not be contradictory

“What is intelligence?” Whether facing the so-cal...

How do effective exhibition advertisers promote their products?

Today I want to talk to you about how exhibition ...

Hot! Who grabbed the "ceiling among ceilings"?

"Who grabbed the 'ceiling among ceilings...

Crunchbase: 40% of the top 30 AI companies with the most funding are from China

From robot baristas to self-driving cars, robo-ad...

Insights: The best life for adults

Famous Artists Gallery | Chen Banding, also known...