|
I am slowly learning SwiftUI - things got "complicated" recently, and in an attempt to understand what is happening I put some (a lot) tracing prints everywhere. One thing this showed me is that many views were being updated often when they didn't need to be. The problem appears to be with how I am using @EnvironmentObject. I created an object that holds some generally used "flags" and injected it into the Environment as an EnvironmentObject:
This way I could just put a @EnvironmentObject at the start of any View that might need one of them and have access to all of them. I assumed SwiftUI would only pay attention to the ones referenced in the individual View, even though all are published.
I think this not a good idea. It results in many Views being updated when they don't need to be, depending on the view hierarchy. I have changed this to have individual observable vars and then views only watch the ones they are interested in: this var in the composite class
was replaced by an individual class:
I needed to make this a class (type), so I could share it using the EnvironmentObject mechanism, since there can be only one instance of each type in the EnvironmentObject. This seems to solve my issue of views being refreshed more often than they need to be. So, my question is, for those here that understand this better than I do, I am helping or hurting my self - is this a safer way to explicitly control the refreshing of views, or should I trust the "Force" (SwiftUI) to figure it all out and put it all back into a single big settings class? |
|
|
|
How would that be different than using individual EnvironmentObjects for each state flag/var? |
|
You don't need a separate object for it. You can read the value you're interested in directly in the view and you don't have to pass a object around. Depending on your use case it may be an option. |
|
For app settings By injecting these settings into the Now, if I understand your intention correctly, since you will make these checks or flags frequently, and aiming to "encapsulate" them in one place instead of repeting code all over, you went with the class. An alternative would be to have ProjectSettings as a |
|
@MarcusKay Thank you. But, the point is that they are "global variables". As an C++ programmer for a long time, the idea of global variables is an anapthema to me. BUT... it seems SwiftUI needs/wants/uses Globals to share state. The point of these variables is to maintain application wide state - the state being various compbinations of views and other things in various states - being shown, not shown, etc. Think of it as a part of the View Model - which is where I have them located in my folder structure in the app. As far as the UserDefaults, I thought that @EnvironmentObject is basically @UserDefaults with a few extras thrown in? To quote our fearless leader:
When one of them says, "this view is now shown" the app needs to rebuild the View tree so that one is shown - like if a local @State var viewIsShown: Bool would be used, but that would then require passing the var around to all the views that might change it and binding it as an incoming var in those views. By, Using the @EnvironmentObject I get them automatically shared to all sub views, and I get them published and observed without having to do anything myself. The issue I am experiencing is that the publishing and observing seems to be associated with the class and not the individual vars within that Class. But, I certainly could be wrong. Seemed like a good idea at the time - but, they are still basically "globals" which gives me serious indigestion. However, it seems that SwiftUI uses globals - like it or not. They just call them something else and look the other way. Sort of like "Binding" appears (from what I can tell) is just another name for what C++ calls a reference - Bindings even use the same syntax as pass-by-reference - ie. $someVar or $someFunc. And it seems to work the same. |
|
I am intimately familiar with that indigestion 😉. A better way to see what is happening though would be to use instruments. They are more technical but certainly more accurate. You might want to give them a shot. This link helps. Some stuff might have changed (it's a 1 yr old link), but it's a starting point. Helped give me the foundation to start experiment with them. https://www.avanderlee.com/debugging/xcode-instruments-time-profiler/ PS: I did forget your last paragraph when answering. Hence the rather naive recommendation. Sorry about that. PPS: I do recall reading about lazy loading of views but didn't really get into that, as I wanted to wrap my head around SwiftUI fundamentals first. Might also be worth a check. I would trust the "Force" 👍 |
SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until April 28th.
Sponsor Hacking with Swift and reach the world's largest Swift community!
This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.
All interactions here are governed by our code of conduct.
Link copied to your pasteboard.