ARTICLE AD BOX
randomBackgroundColor always gets called when its enclosing body is evaluated, regardless of the dependencies of the view to which it is applied. After all, randomBackgroundColor is just a regular Swift function. You call it in body, so every time body gets evaluated, a new random color gets created.
In A,
struct A: View { var body: some View { Text("ASD") .padding() .randomBackgroundColor() } }The text does not change color not because the text does not have dependencies, but because A does not have dependencies.
In B,
struct B: View { @Binding var num: Int var body: some View { HStack { Text("\(num)") .padding() .randomBackgroundColor() // color changes. Correct since its dependency changes C(fixed: "Fixed Text") .randomBackgroundColor() // does not change color. Correct since the text remains the same } } }Both Text("\(num)") and C change colors when num changes, because num is a dependency of B. Whenever num changes, B.body gets called.
You can't visually see C changing color, because there is an additional randomBackgroundColor in C.body which completely covers up the background you added in B.body. Since C does not have dependencies, C.body is only called once and therefore the only background that you can visually see does not change.
Now the behavior in Test should seem a lot more consistent. Test has vm.num as a dependency, so when vm.num changes, Test.body gets called, and all three .randomBackgroundColor() in it gets called. As a result, Text("ASD"), B, as well as C, all get a new color. Again, the new color that C got is completely covered up by the background added in C.body.
Side note:
Instead of directly applying a new color in randomBackgroundColor, you could extract the implementation into a ViewModifier,
extension View { func randomBackgroundColor() -> some View { modifier(RandomBackgroundColorModifier()) } } struct RandomBackgroundColorModifier: ViewModifier { func body(content: Content) -> some View { content.background { Color(cgColor: .init( red: .random(in: 0...1.0), green: .random(in: 0...1.0), blue: .random(in: 0...1.0), alpha: 1)) } } }In this case, a new color gets created only when RandomBackgroundColorModifier.body is called. Since RandomBackgroundColorModifier does not have any dependencies, all your views' backgrounds will not change (unless their identity changes).
