Saturday, October 5, 2024
HomeiOS DevelopmentSheets don’t inherit the surroundings – Ole Begemann

Sheets don’t inherit the surroundings – Ole Begemann

[ad_1]

This habits has been mounted. As of Xcode 12.0 (the iOS 14.0/macOS 11.0 SDKs), sheets do inherit their surroundings.


Not like different views, modal sheets in SwiftUI do not inherit the surroundings from their guardian.

The surroundings is SwiftUI’s technique to move information implicitly to little one views. Amongst different issues, the surroundings accommodates app- or system-wide preferences, such because the consumer’s locale or the present coloration scheme. Primarily, you’ll be able to consider the surroundings as a big, heterogeneous dictionary that will get handed implicitly to each view.

Many built-in SwiftUI views take the surroundings under consideration after they draw themselves. We are able to make the most of this to override a setting for all little one views with a single line of code. Contemplate this instance:


SwiftUI view displaying three rows of text, where the text views in the middle row have a larger font size
The one .font modifier overrides the font for all little one views.
VStack(spacing: 8) {
  Textual content("Line 1")
  HStack {
    Textual content("Line 2")
    VStack {
      Textual content("Line 2a")
      Textual content("Line 2b")
    }
  }.font(.title)
  Textual content("Line 3")
}

The .font(.title) modifier on the HStack mutates the corresponding worth within the present surroundings, which then will get handed to the stack’s little one views. And since Textual content grabs its font from the surroundings, all textual content views on this part of the view tree are rendered with a bigger font dimension. Notice that the modified surroundings additionally applies to oblique kids of the HStack.

The next instance creates a root view whose locale and dynamic sort dimension have been overridden within the surroundings. The view shows a formatted date and the present dynamic sort dimension setting. Right here’s the code for the foundation view:

struct RootView: View {
  var physique: some View {
    RootViewContent()
      .surroundings(.sizeCategory, .accessibilityMedium)
      .surroundings(.locale, Locale(identifier: "ja_JP"))
  }
}

struct RootViewContent: View {
  @State var isPresentingSheet = false
  @Setting(.sizeCategory) var sizeCategory

  var physique: some View {
    VStack(spacing: 16) {
      Textual content("Root View").font(.title)
      Textual content("(Date(), formatter: dateFormatter)")
      Textual content("Dimension class: (String(describing: sizeCategory))")
      Button("Open Sheet") {
        self.isPresentingSheet = true
      }
    }
    .sheet(isPresented: self.$isPresentingSheet) {
      ChildView()
    }
  }
}

Tapping the button within the root view units a state variable that triggers the presentation of a modal sheet, utilizing the .sheet modifier:

    // …
    .sheet(isPresented: self.$isPresentingSheet) {
      ChildView()
    }
    // …

The view that will get offered shows the identical information as the foundation view, with out modifying the surroundings in any approach:

struct ChildView: View {
  @Setting(.sizeCategory) var sizeCategory

  var physique: some View {
    VStack(spacing: 16) {
      Textual content("Baby View").font(.title)
      Textual content("(Date(), formatter: dateFormatter)")
      Textual content("Dimension class: (String(describing: sizeCategory))")
    }
  }
}

I’d anticipate that the offered view inherits the surroundings from the presenting view (some modifications however for the reason that presentation mode can also be saved within the surroundings), however that’s clearly not the case; whereas the foundation view appropriately makes use of the Japanese locale and a really giant dynamic sort setting, the kid view goes again to the system locale and textual content dimension:


Screenshots of the presenting view displaying large text and a Japanese-formatted date, and the presented view displaying normal text and an English-formatted date.
The presenting view didn’t move its surroundings to the offered view.

I’m unsure if that is intentional or a bug. (Replace: It’s a bug.) I suppose for those who see sheets as impartial entities that shouldn’t be affected by their presenting view, it is sensible for some surroundings values to not get propagated. Examples of this sort may embody:

For different settings, resembling locale and dynamic sort dimension, not propagating appears the unsuitable option to me. It seems like there isn’t any single choice that works for every thing, although. And making this a configurable habits that each EnvironmentKey can resolve for itself may be complicated.

If you wish to propagate an surroundings worth to a sheet, you will need to achieve this manually. In our instance, the code would seem like this:

    // …
    .sheet(isPresented: self.$isPresentingSheet) {
      ChildView()
        .surroundings(.sizeCategory, self.sizeCategory)      
        .surroundings(.locale, self.locale)
    }
    // …

(This assumes that you just additionally added a property @Setting(.locale) var locale to the foundation view in an effort to entry the present locale contained in the surroundings.)



[ad_2]

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments