I'm using this answer to init an ObservableObject
with the horizontalSizeClass
: https://stackoverflow.com/a/73339015 . What this achieves is to set the blue rectangle to visible on regular sized devices and invisible on compact devices on init. So far so good.
The problem is that the Settings
object will of course be re-initalized when the size class changes (for example when rotating an iPhone 13 Pro Max between portrait and landscape). For the user this can result in the blue rectangle appearing or disappearing. What I can't figure out is how I can init isVisible
based on the horizontal size class once, but not create a new instance when the horizontal size class changes later to keep the current value of isVisible
. Is this even possible?
Code:
struct ContentView: View {
@Environment(\.horizontalSizeClass) var horizontalSizeClass
struct MainView: View {
@EnvironmentObject var settings: Settings
var body: some View {
VStack {
Button("Toggle Visibility") {
settings.isVisible.toggle()
}
Rectangle()
.frame(width: 100, height: 100)
.foregroundColor(.blue)
.opacity(settings.isVisible ? 1 : 0)
}
.animation(.linear(duration: 2.0), value: settings.isVisible)
}
}
var body: some View {
MainView()
.environmentObject(
Settings(isVisible: horizontalSizeClass == .regular)
)
}
}
class Settings: ObservableObject {
@Published var isVisible: Bool
init(isVisible: Bool) {
self.isVisible = isVisible
}
}
CodePudding user response:
isVisible should init with a specific value depending on the size class, but then it should only be decided by the user if it is visible of not. It should not "automatically" change when the device is rotated.
then approach should be different - we will inject state of horizontalSizeClass
as initial value and use initializable-once feature of StateObject
...
here is main changed parts (tested with Xcode 13.4 / iOS 15.5)
// injection
var body: some View {
MainView(isVisible: horizontalSizeClass == .regular)
}
// initialisation
struct MainView: View {
@StateObject var settings: Settings
init(isVisible: Bool) {
_settings = StateObject(wrappedValue: Settings(isVisible: isVisible))
}
everything else is same as before.