What's new in SwiftUI iOS 16.4 beta 2
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 ofTimelineView<_, _>
.Context into its content closure have been deprecated in this release, and replaced with equivalent versions that pass an instance ofTimelineViewDefaultContext
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:
- Swift Data init with heap buffer from C and free in Swift
- DispatchQueue QoS Order Explained Best Practices & Common Pitfalls to Avoid
- iOS RUNNINGBOARD 0xdead10cc crash troubleshooting
- iOS objc_retain crash troubleshooting
- Fastlane Best Practices for iOS and Troubleshooting Tips
- SwiftUI: How to Tap to Select All Text in a TextField on iOS
- Direct Download Link for All Xcode Releases/Beta, Compilers and SDK Information
- Guide: Jailbreaking Apple TV 4K
- iOS Security: App security in iOS and iPadOS - code signing, entitlement and sandbox etc.
- Tips on Use Swift Package Manager (SPM) with Continuous Integration / Delivery (CI/CD)
- Jailbreak iPhone 8 iOS 16.2 with palera1n and use frida dump to decrypt ipa
- Use frida and objection to penetration test iOS app security
- Troubleshooting: iOS auto layout warning about UIView-Encapsulated-Layout-Height
- Troubleshooting: loading carthage framework error: dyld: Library not loaded: @rpath/...
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