Skip to content

Use StateObject in Settings view to avoid parent view updates from re…#558

Closed
gestrich wants to merge 1 commit into
LoopKit:devfrom
gestrich:bugfix/2025-04/therapy-settings-view-state
Closed

Use StateObject in Settings view to avoid parent view updates from re…#558
gestrich wants to merge 1 commit into
LoopKit:devfrom
gestrich:bugfix/2025-04/therapy-settings-view-state

Conversation

@gestrich

@gestrich gestrich commented Apr 19, 2025

Copy link
Copy Markdown
Contributor

For LoopKit/Loop#2267

This PR tackles the state‑loss problem that arises when TherapySettingsViewModel is instantiated inline inside SettingsView.

What’s happening

  1. View‑model recreation
    Because the view model is created inside the body of SettingsView, every SwiftUI refresh tears it down and builds a new one. Any changes to the View Model (e.g. basal‑rate schedule changes) disappears until the upstream data source happens to publish again.

  2. Silent nested mutations (not fixing this - but FYI)
    TherapySettingsViewModel.therapySettings is a single @published value. Mutating its nested properties doesn’t emit a change unless the containing struct itself is reassigned, so some updates never reach the UI. It's not clear if this is affecting the refreshes but this may be something to visit in the future.

Scope of this PR

This PR fixes problem 1 by converting the view model from @ObservedObject to @StateObject, anchoring its lifetime to the view hierarchy instead of the render cycle.

Trade‑offs / testing notes

  • Pros: UI state survives parent refreshes.
  • Cons: The view will no longer automatically pick up parent‑level updates but it's not clear we are expecting updates from the parent Settings view. Verify that changing various therapy settings still refreshes when expected.

I believe this therapy settings view is used during app setup, so that will need tested too.

@marionbarker

Copy link
Copy Markdown
Contributor

Test

  • Confirmed that LoopWorkspace dev branch exhibits Loop Issue 2267
  • Confirmed that LoopWorkspace tidepool-merge branch does NOT exhibit Loop Issue 2267

Apply modification to LoopWorkspace dev branch

Success: Issue 2267 is fixed

Apply modification to LoopWorkspace tidepool-merge branch

Success: tidepool-merge works as expected

@marionbarker marionbarker requested a review from ps2 April 19, 2025 17:24

@marionbarker marionbarker left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved by test.

@gestrich gestrich marked this pull request as ready for review April 20, 2025 11:48
@motinis

motinis commented Apr 20, 2025

Copy link
Copy Markdown

This worked for me as well!

@marionbarker

Copy link
Copy Markdown
Contributor

Status

I think this test indicates the modification in PR 558 is acceptable. Happy to do additional tests as requested.

Test of Onboarding

Because of @gestrich statement "The view will no longer automatically pick up parent‑level updates", I decided to test this with onboarding.

Test Plan

Each of the numbered tests was performed side-by-side on 2 SE phones running iOS 18.4.

  • original: One phone is configured with main 3.4.4 (2nd gen SE)
  • proposed: One phone is configured with dev and LoopKit PR 558 (3rd gen SE)

For all tests, after onboarding is completed, add pump (Pump Simulator) and CGM (NS as CGM). Then test for Issue 2267.

  1. Onboard without using Nightscout, enter all settings manually
  2. Onboard using Nightscout, accept values as read from Nightscout
  3. Onboard using Nighstcout, but when reaching the final review screen:
    • back up to the Basal Rates screen
    • make a change in one rate
    • confirm change registers on basal rate screen
    • confirm change registers on final review screen
    • back up again to restore original rate (don't want change to be reflected in Nightscout profile)
    • accept at final review and continue

Test Results

  • original: Exhibited Issue 2267 but in no other basal rate interaction was there stale data displayed
  • proposed: Basal Rate data was always displayed properly

In other words, the original phone displayed stale data only after Onboarding was complete and for the case of modifying a Basal Rate, saving it to a pump and then viewing the stale rate on the Therapy Setting screen under Basal Rates section. Once exiting that screen and returning, the updated Basal Rate schedule was displayed.

@ps2 ps2 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the testing, Marion. I'm stil not sure this is the right fix, and I'm hesitant to put this in as there may be other side effects from not publishing settings updates. Interdependent settings, like how corrections ranges affect what you're allowed to enter for suspend threshold, or vice versa, might be affected. It's also a display only bug; the data does get saved, and the workaround is simple; just ignore the non-updated setting.

@ps2

ps2 commented Apr 22, 2025

Copy link
Copy Markdown
Collaborator

There are changes to how this works coming in tidepool-merge (and Tidepool code that isn't in tidepool-merge branches yet).

@gestrich gestrich closed this Apr 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants