RSS

What's new in SwiftUI iOS 16.4 beta 2

What’s new in SwiftUI iOS 16.4 beta 2: new view modifiers, navigation fixes etc.

iOS & iPadOS 16.4 Beta 2 Released on Feb 28, 2023. Here is what’s the change on SwiftUI.

New Features in SwiftUI iOS 16.4 beta 2

A family of new view modifiers lets you build even richer resizable sheet experience with SwiftUI. Use these new modifiers to make the view behind a sheet interactive, provide a translucent background, control scrolling and expansion behavior, and even adjust the corner radius of the sheet.

To let people interact with the content behind a sheet, use the .presentationBackgroundInteraction(_:) modifier. The following example enables people to interact with the view behind the sheet when the sheet is at the smallest detent, but not at the other detents:

   struct ContentView: View {
       @State private var showSettings = false


       var body: some View {
           Button("View Settings") {
               showSettings = true
           }
           .sheet(isPresented: $showSettings) {
               SettingsView()
                   .presentationDetents(
                       [.height(120), .medium, .large])
                   .presentationBackgroundInteraction(
                       .enabled(upThrough: .height(120)))
           }
       }
   }

Give your sheet a translucent background with the new presentationBackground(_:) modifier. The following example uses the thick material as the sheet background:

  struct ContentView: View {
      @State private var showSettings = false

      var body: some View {
          Button("View Settings") {
              showSettings = true
          }
          .sheet(isPresented: $showSettings) {
              SettingsView()
                  .presentationBackground(.thickMaterial)
           }
       }
   }

Add a custom view as the background of your sheet with the presentationBackground(alignment:content:) modifier.

By default, when a person swipes up on a scroll view in a resizable presentation, the presentation grows to the next detent. A scroll view embedded in the presentation only scrolls after the presentation reaches its largest size. Use the new presentationContentInteraction(_:) modifier to control which action takes precedence.

For example, you can request that swipe gestures scroll content first, resizing the sheet only after hitting the end of the scroll view, by passing the .scrolls value to this modifier:

   struct ContentView: View {
       @State private var showSettings = false


       var body: some View {
           Button("View Settings") {
               showSettings = true
           }
           .sheet(isPresented: $showSettings) {
               SettingsView()
                   .presentationDetents([.medium, .large])
                   .presentationContentInteraction(.scrolls)
           }
       }
   }

Apply the new .presentationCompactAdaptation(_:) modifier to the content of a modal presentation to control how it adapts to compact size classes on iPad and iPhone.

For example, the popover modifier presents a popover on iPad. By default, a popover adapts to the narrow horizontal size class on iPhone by showing as a sheet. In the example below, the .presentationCompactAdaptation(.none) modifier asks SwiftUI to show this as a popover on iPhone as well.

  struct PopoverExample: View {
      @State private var isShowingPopover = false

      var body: some View {
          Button("Show Popover") {
              self.isShowingPopover = true
          }
          .popover(isPresented: $isShowingPopover) {
              Text("Popover Content")
                  .padding()
                  .presentationCompactAdaptation(.none)
          }
      }
  }

Use .presentationCompactAdaptation(horizontal:vertical:) to adapt differently in horizontally and vertically compact size classes. (103257577)

Resolved SwiftUI Issues in iOS 16.4 beta2

  • Fixed: ScrollView has improved support for right to left languages by default. If you have a ScrollView that shouldn’t change its behavior in right to left languages, use the .environment(.layoutDirection, .leftToRight) modifier to ensure the ScrollView always sees a left to right layout direction. (65108729)

  • Fixed: Refreshable modifiers applied to lists will no longer also apply to lists or scroll views within the content of that list. Re-apply a refreshable modifier to the content of the list if this is desired behavior. (102052575)

  • Fixed: The no-argument presentationBackground() modifier has been removed. Use one of the overloads taking an explicit ShapeStyle or View instead. (105598868)

Deprecations SwiftUI in iOS 16.4 beta2

  • TimelineView initializers that pass an instance of TimelineView<_, _>.Context into its content closure have been deprecated in this release, and replaced with equivalent versions that pass an instance of TimelineViewDefaultContext instead.

  • Several table initializers that were previously deprecated and replaced in iOS 16.2 and macOS 13.1 have now been removed from the API. Using these initializers will now generate a build error, with a Fix-It to switch to the replacement initializer API. For code that doesn’t generate this error, no action is needed.

This change, along with other improvements in the Swift compiler, improve the performance of compiling Swift and SwiftUI code.

The new, replacement API adds a parameter, of:, that identifies the type of the Table’s row values separately from the initializer’s row and column content closure parameters. This improves compilation performance in two ways. First, by knowing the row value type up-front, the compiler doesn’t need to infer that type from the body implementations of each closure. Second, the compiler can immediately enforce that each closure uses the same row value type in its body implementation, instead of needing to verify that the inferred types are equal after evaluating each closure.

The following examples show code for creating a Table before and after adoption of the new API:

// before (will now produce an error):
Table {
	TableColumn("Name", value: \.name)
  TableColumn("Email", value: \.email)
} rows: {
  ForEach(people) { person in
  	TableRow(person)
  }
}

// after:
Table(of: Person.self) {
  TableColumn("Name", value: \.name)
  TableColumn("Email", value: \.email)
} rows: {
  ForEach(people) { person in
  	TableRow(person)
  }
}

SwiftUI Navigation changes on iOS 16.4 beta2

Resolved Issues

  • Fixed: Navigation destinations nested within NavigationStack and NavigationSplitView are detected more performantly and reliably, no longer logging update cycles. (97597634)

  • Fixed: Navigation destinations that present a new view on top of a NavigationSplitViewColumn (rather than pushing a view onto a stack in that column) no longer cause an assertion failure on iOS or infinite loop on macOS when the destination view is itself a NavigationStack.

  • For example, the below construction is functional

NavigationSplitView {
    SidebarView()
    .navigationDestination(isPresented: $present) {
        NavigationStack { ... }
    }
} detail: { ... }
(103278180)
  • Fixed: Navigation destinations with data dependencies captured from ancestor views update more reliably.
struct DataDependentNavigation: View {
  @State var changeColor: Bool = false
  @State var present: Bool = false


  var body: some View {
  NavigationSplitView {
    Color.blue
      .navigationDestination(isPresented: $present) {
           // This is a data dependency from an ancestor view
            changeColor ? Color.green : Color.yellow
      }
  } detail: {
    Color.teal
  }
}

Related pages:

References

OmniLock - Block / Hide App on iOS

Block distractive apps from appearing on the Home Screen and App Library, enhance your focus and reduce screen time.

DNS Firewall for iOS and Mac OS

Encrypted your DNS to protect your privacy and firewall to block phishing, malicious domains, block ads in all browsers and apps

Ad