Tuesday, August 16, 2022
HomeiOS DevelopmentSheets don’t inherit the setting – Ole Begemann

Sheets don’t inherit the setting – Ole Begemann


This conduct has been fastened. As of Xcode 12.0 (the iOS 14.0/macOS 11.0 SDKs), sheets do inherit their setting.


Not like different views, modal sheets in SwiftUI do not inherit the setting from their father or mother.

The setting is SwiftUI’s option to cross information implicitly to baby views. Amongst different issues, the setting accommodates app- or system-wide preferences, such because the person’s locale or the present colour scheme. Primarily, you’ll be able to consider the setting as a big, heterogeneous dictionary that will get handed implicitly to each view.

Many built-in SwiftUI views take the setting into consideration after they draw themselves. We will reap the benefits of this to override a setting for all baby views with a single line of code. Think about this instance:



The only .font modifier overrides the font for all baby 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 setting, which then will get handed to the stack’s baby views. And since Textual content grabs its font from the setting, all textual content views on this part of the view tree are rendered with a bigger font measurement. Word that the modified setting additionally applies to oblique kids of the HStack.

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

struct RootView: View {
  var physique: some View {
    RootViewContent()
      .setting(.sizeCategory, .accessibilityMedium)
      .setting(.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 setting in any manner:

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 count on that the offered view inherits the setting from the presenting view (some modifications however because the presentation mode can be saved within the setting), however that’s clearly not the case; whereas the foundation view accurately makes use of the Japanese locale and a really giant dynamic kind setting, the kid view goes again to the system locale and textual content measurement:


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 cross its setting to the offered view.

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

For different settings, corresponding to locale and dynamic kind measurement, not propagating appears the mistaken option to me. It appears to be like like there is no such thing as a single choice that works for all the things, although. And making this a configurable conduct that each EnvironmentKey can resolve for itself may be complicated.

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

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

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



RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular