Hello!
I have experienced a weird bug in iOS 26 Beta (8) and previous beta versions. The safe area inset is not correctly aligned with the keyboard toolbar on real devices and simulators.
When you focus a new textfield the bottom safe area is correctly placed aligned the keyboard toolbar.
On real devices the safe area inset view is covered slightly by the keyboard toolbar, which is even worse than on the simulator.
Here's a clip from a simulator:
Here's the code that reproduced the bug I experienced in our app.
#Preview {
NavigationStack {
ScrollView {
TextField("", text: .constant(""))
.padding()
.background(Color.secondary)
TextField("", text: .constant(""))
.padding()
.background(Color.green)
}
.padding()
.safeAreaInset(edge: .bottom, content: {
Color.red
.frame(maxWidth: .infinity)
.frame(height: 40)
})
.toolbar {
ToolbarItem(placement: .keyboard) {
Button {} label: {
Text("test")
}
}
}
}
}
SwiftUI
RSS for tagProvide views, controls, and layout structures for declaring your app's user interface using SwiftUI.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
have a SwiftUI View where I can edit financial transaction information. The data is stored in SwiftData. If I enter a TextField element and start typing, it is super laggy and there are hangs of 1-2 seconds between each input (identical behaviour if debugger is detached). On the same view I have another TextField that is just attached to a @State variable of that view and TextField updates of that value work flawlessly. So somehow the hangs must be related to my SwiftData object but I cannot figure out why.
This used to work fine until a few months ago and then I could see the performance degrading.
I have noticed that when I use a placeholder variable like
@State private var transactionSubject: String = ""
and link that to the TextField, the performance is back to normal. I am then using
.onSubmit {
self.transaction.subject = self.transactionSubject
}
to update the value in the end but this again causes a 1 s hang. :/
Below the original code sample with some unnecessary stuff removed:
struct EditTransactionView: View {
@Environment(\.modelContext) var modelContext
@Environment(\.dismiss) var dismiss
@State private var testValue: String = ""
@Bindable var transaction: Transaction
init(transaction: Transaction) {
self.transaction = transaction
let transactionID = transaction.transactionID
let parentTransactionID = transaction.transactionMasterID
_childTransactions = Query(filter: #Predicate<Transaction> {item in
item.transactionMasterID == transactionID
}, sort: \Transaction.date, order: .reverse)
_parentTransactions = Query(filter: #Predicate<Transaction> {item in
item.transactionID == parentTransactionID
}, sort: \Transaction.date, order: .reverse)
print(_parentTransactions)
}
//Function to keep text length in limits
func limitText(_ upper: Int) {
if self.transaction.icon.count > upper {
self.transaction.icon = String(self.transaction.icon.prefix(upper))
}
}
var body: some View {
ZStack {
Form{
Section{
//this one hangs
TextField("Amount", value: $transaction.amount, format: .currency(code: Locale.current.currency?.identifier ?? "USD"))
//this one works perfectly
TextField("Test", text: $testValue)
HStack{
TextField("Enter subject", text: $transaction.subject)
.onAppear(perform: {
UITextField.appearance().clearButtonMode = .whileEditing
})
Divider()
TextField("Select icon", text: $transaction.icon)
.keyboardType(.init(rawValue: 124)!)
.multilineTextAlignment(.trailing)
}
}
}
.onDisappear(){
if transaction.amount == 0 {
// modelContext.delete(transaction)
}
}
.onChange(of: selectedItem, loadPhoto)
.navigationTitle("Transaction")
.navigationBarTitleDisplayMode(.inline)
.toolbar{
Button("Cancel", systemImage: "trash"){
modelContext.delete(transaction)
dismiss()
}
}
.sheet(isPresented: $showingImagePickerView){
ImagePickerView(isPresented: $showingImagePickerView, image: $image, sourceType: .camera)
}
.onChange(of: image){
let data = image?.pngData()
if !(data?.isEmpty ?? false) {
transaction.photo = data
}
}
.onAppear(){
cameraManager.requestPermission()
setDefaultVendor()
setDefaultCategory()
setDefaultGroup()
}
.sheet(isPresented: $showingAmountEntryView){
AmountEntryView(amount: $transaction.amount)
}
}
}
}
I have a custom list and I want to make the names in the list editable through double tap. I know how to solve this hacky ways.
But are there no solid way to achieve this? like having .disabled without graying it out?
Topic:
UI Frameworks
SubTopic:
SwiftUI
The following code shows that a selected button in a list gots blurred if a glass effect is applied to the list. This happens if the button style is plain or glass. It does not happen if the button style is bordered. Is this a wanted documented behavior or is this a bug?
struct ContentView: View {
@State private var items = [
"Item 1", "Item 2", "Item 3", "Item 4"]
var body: some View {
ZStack {
Image(systemName: "globe")
.resizable()
List(items, id: \.self) { item in
Button(action: {}, label: { Text(item) })
}
.padding()
.glassEffect(in: Rectangle())
}
}
}
Environment
iOS Version: iOS 26 Beta 8
Xcode Version: iOS 26 Beta 6
StoreKit: StoreKit 2
Description
When calling AppStore.showManageSubscriptions(in:) on iOS 26 beta, I'm experiencing an unusual presentation behavior that wasn't present in earlier versions.
An empty/blank view appears first
Then the actual StoreKit manage subscriptions sheet appears on top
When dismissing the StoreKit sheet, it closes properly
But then I have to dismiss the empty view underneath as well
This creates a poor user experience showing double sheets.
Code Sample
@MainActor
func showManageSubscriptions() {
guard let scene = UIApplication.shared.connectedScenes
.first(where: { $0 is UIWindowScene }) as? UIWindowScene else {
return
}
Task {
do {
try await AppStore.showManageSubscriptions(in: scene)
} catch {
// Handle error
}
}
}
Expected Behavior
The StoreKit manage subscriptions sheet should present directly without any intermediate empty view, as it did in previous iOS versions.
Actual Behavior
An empty view layer appears between my app and the StoreKit sheet, requiring users to dismiss twice.
Questions
Is anyone else experiencing this issue with iOS 26 beta?
Is this a known beta issue that will be addressed?
Are there any recommended workarounds while waiting for a fix?
Hello,
I’ve encountered what seems to be a bug with the keyboard dismissal animation on iOS 26.0 Beta (25A5349a), Xcode Version 26.0 beta 5 (17A5295f).
When dismissing the keyboard from a SwiftUI TextField using @FocusState, the keyboard does not animate downward as expected. Instead, it instantly disappears, which feels jarring and inconsistent with system behavior.
I am attaching a short video demonstrating the issue. Below is the minimal reproducible code sample:
//
// ContentView.swift
// TestingKeyboardDismissal
//
// Created by Sasha Morozov on 27/08/25.
//
import SwiftUI
struct ContentView: View {
@State private var text: String = ""
@FocusState private var isFocused: Bool
var body: some View {
ZStack {
Color.clear.ignoresSafeArea()
VStack(spacing: 20) {
TextField("Enter text here...", text: $text)
.textFieldStyle(.roundedBorder)
.focused($isFocused)
.padding(.horizontal)
HStack {
Button("Focus") { isFocused = true }
.buttonStyle(.borderedProminent)
Button("Unfocus") { isFocused = false }
.buttonStyle(.bordered)
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
.padding()
}
.ignoresSafeArea(.keyboard, edges: .bottom)
}
}
#Preview {
ContentView()
}
Steps to reproduce:
Run** the app on iOS 26.0 beta 5 (17A5295f).
Tap Focus → keyboard appears as expected.
Tap Unfocus → keyboard disappears instantly without the usual slide-down animation.
Expected result:
Keyboard should animate smoothly downwards when dismissed.
Actual result:
Keyboard instantly vanishes without animation.
p.s. we should be really able to upload videos here for demostration
I really enjoyed using SwiftData for persistence until I found out that the CloudKit integration ensures changes are only eventually consistent, and that changes can propagate to other devices after as long as minutes, making it useless for any feature that involves handoff between devices. Devastating news but I guess it’s on me for nrtfm. I may try my hand at a custom model context DataStore integrating Powersync, but that’s a whole trip and before I embark on it I was wondering if anyone had suggestions for resolving this problem in a simple and elegant manager that allows me to keep as much of the machinery within Apple’s ecosystem as possible, while ensure reliable “live” updates to SwiftData stores on all eligible devices.
Hi guys!
I wanted to study this new ManipulationComponent(), but I keep getting a warning that I don’t understand, even in a very simple scenario.
i don't have any collisions just binding the Manipulation
the warning message is :
** Entity returned from EntityWrapper.makeEntity(context:) was already parented to another entity. This is not supported and may lead to unexpected behavior. SwiftUI adds entities to internally-managed entity hierarchies.**
RealityView { content, attachments in
if let loadedModel = try? await Entity(named: "cloud_glb", in: realityKitContentBundle) {
content.add(loadedModel)
loadedModel.components.set(ManipulationComponent())
}
Thanks !
In my SwiftUI iOS app, I need to detect which key (and modifier flags – Command, Option, Shift, Control) a user presses, but I don't want to pre-register them using .keyboardShortcut(_:modifiers:).
My use case is that keyboard shortcuts are user-configurable, so I need to capture the actual key + modifier combination dynamically at runtime and perform the appropriate action based on the user’s settings.
Questions:
What is the recommended way to detect arbitrary key + modifier combinations in SwiftUI on iOS?
Is there a SwiftUI-native solution for this, or should I rely on UIPressesEvent and wrap it with UIViewControllerRepresentable?
If UIKit bridging is necessary, what is the cleanest pattern for integrating this with SwiftUI views (e.g., Buttons)?
Any official guidance or best practices would be greatly appreciated!
I've been exploring the resources from WWDC25 Session 280: "Code-along: Cook up a rich text experience in SwiftUI with AttributedString" and the SwiftUI documentation on "Building rich SwiftUI text experiences." After spending some time experimenting and trying to implement these features with these APIs on iOS26 , I’ve run into a specific question.
Is there a way to programmatically trigger the Format Sheet directly—for example, from a custom button—rather than requiring the user to go through the multi-step process of selecting text, opening the context menu, tapping "Format," and then selecting "More"?
I’d like to provide a more streamlined editing experience in my app. Any guidance would be greatly appreciated!
In SwiftUI for macOS, when implementing a DragGesture inside a ScrollVIew, how can I implement auto-scrolling when the mouse is not actively moving?
In AppKit, this would normally be done with a periodic event so that auto-scrolling continues to take place even if the user isn't actively moving the mouse. This is essential behaviour when implementing something like a drag-to-select gesture.
NSView.autoscroll(with: NSEvent) -> Bool
Is there anything in SwiftUI or ScrollView to accomplish this behaviour?
Hi,
In the WWDC25 session Elevate an app with Swift concurrency (timestamps: 8:04 and later), the StickerViewModel is shown annotated with @Observable but not @MainActor. The narration mentions that updates happen on the main thread, but that guarantee is left implicit in the calling code.
In Swift 6, though, one of the major benefits is stronger compiler enforcement against data races and isolation rules. If a view model were also annotated with @MainActor, then the compiler could enforce that observable state is only updated on the main actor, preventing accidental background mutations or updates that can cause data races between nonisolated and main actor-isolated uses.
Since @Observable already signals that state changes are intended to be observed (and in practice, usually by views), it seems natural that such types should also be main-actor isolated. Otherwise, we’re left with an implicit expectation that updates will always come from the main thread, but without the compiler’s help in enforcing that rule.
This also ties into the concept of local reasoning that was emphasized in other Swift 6 talks (e.g. Beyond the basics of structured concurrency). With @MainActor, I can look at a view model and immediately know that all of its state is main-actor isolated. With only @Observable, that guarantee is left out, which feels like it weakens the clarity that Swift 6 is trying to promote.
Would it be considered a best practice in Swift 6 to use both @Observable and @MainActor for UI-facing view models? Or is the intention that SwiftUI developers should rely on calling context to ensure main-thread updates, even if that means the compiler cannot enforce isolation?
Thanks!
Is it possible to add an ornament below a tab bar like this? Or does the whole side bar have to be an ornament to build this?
NavigationLinks do not display correctly in tvOS 26. When using a Button, the correct behavior of vertically placing an Image or AsyncImage above one or two Text fields occurs. However, when using NavigationLink the image and text(s) are laid out horizontally. Attempting to fix this using a VStack prevents the text from sliding down as the NavigationLink receives focus. Using the hoverEffect modifier does not help.
Using a Button (correct behavior):
Using a NavigationLink without VStack:
Using a NavigationLink with VStack:
For a number of complex views in my app, I need to embed scrollable objects (like List, Form or TextEditor) in a ScrollView. To do that, I need to apply a limit to the height of the embedded object.
What I would like to do is set that limit to the actual height of the content being displayed in the List, Form, TextEditor, etc. (Note that this height calculation should be dynamic, so that content changes are properly displayed.
I attempted the following:
@State listHeight: CGFloat = .zero
List {
... content here
}
.onScrollGeometryChange(for: CGFloat.self, of: { geometry in
return geometry.contentSize.height
}, action: { oldValue, newValue in
if oldValue != newValue {
listHeight = newValue
}
})
.frame(height: listHeight)
.scrollDisabled(true)
This does not work because geometry.contentSize.height is always 0. So it is apparent that .onScrollGeometryChangedoes not interact with the internal scrolling mechanism of List. (Note, however, that.scrollDisabled` does work.)
Does anyone have a suggestion on how I might get this to work?
If you create a NavigationSplitView, then the sidebar is automatically adorned with a sidebar material effect. This affects the views background as well as any controls that are in the view.
What is the correct way to disable this behaviour so that I can use a NavigationSplitView without the material effects being applied?
The best I've come up with so far is to explicitly set the background on the sidebar but I'm curious if that's the correct way or I'm just getting lucky.
struct ContentView: View {
var body: some View {
NavigationSplitView {
// This works, but is it correct?
SidebarView()
.background(.windowBackground)
} detail: {
DetailView()
}
}
}
Given a View in SwiftUI for macOS, how can I tell if that view is hidden either because it, or any of its ancestor's opacity is 0.0 or the .hidden modifier has been applied?
Presumably I can manually do this with an Environment value on the ancestor view, but I'm curious if this can be done more idiomatically.
An example use case:
I have views that run long-running Tasks via the .task(id:) modifier. These tasks only need to be running if the View itself is visible to the user.
When the View is hidden, the task should stop. When the View reappears, the Task should restart. This happens automatically when Views are created and destroyed, but does not happen when a view is only hidden.
When performing custom layout in AppKit, it's essential that you pixel align frames using methods like backingAlignedRect. The alignment differs depending on the backingScaleFactor of the parent window.
When building custom Layouts in SwiftUI, how should you compute the alignment of a subview.frame in placeSubviews() before calling subview.place(...)?
Surprisingly, I haven't seen any mention of this in the WWDC videos. However, if I create a Rectangle of width 1px and then position it on fractional coordinates, I get a blurry view, as I would expect.
Rounding to whole numbers works, but on Retina screens you should be able to round to 0.5 as well.
func placeSubviews(
in bounds: CGRect,
proposal: ProposedViewSize,
subviews: Subviews,
cache: inout Void
) {
// This should be backing aligned based on the parent window's backing scale factor.
var frame = CGRect(
x: 10.3,
y: 10.8,
width: 300.6,
height: 300.1
)
subview.place(
at: frame.origin,
anchor: .topLeading,
proposal: ProposedViewSize(frame.size)
)
}
I have an app using TabView with multiple Tabs using tabViewStyle „sidebarAdaptable“.
Each Tab does have its own NavigationStack.
When I switch multiple times between the tabs and append a child view to one of my navigation stacks, it will stop working after a few tries with the following error
„A NavigationLink is presenting a value of type “HomeStack” but there is no matching navigationDestination declaration visible from the location of the link. The link cannot be activated.
Note: Links search for destinations in any surrounding NavigationStack, then within the same column of a NavigationSplitView.“
The same code is working fine on iOS, iPadOS but not working on macOS.
When I remove tabViewStyle of sidebarAdaptable it’s also working on macOS.
I shrinked it down to a minimal reproducible code sample.
Any idea if that is a bug or I'm doing something wrong?
struct ContentView: View {
@State private var appState: AppState = .init()
var body: some View {
TabView(selection: $appState.rootTab) {
Tab("Home", systemImage: "house", value: RootTab.home) {
NavigationStack(path: $appState.homeStack) {
Text("Home Stack")
NavigationLink("Item 1", value: HomeStack.item1)
.padding()
NavigationLink("Item 2", value: HomeStack.item2)
.padding()
.navigationDestination(for: HomeStack.self) { stack in
Text("Stack \(stack.rawValue)")
}
.navigationTitle("HomeStack")
}
}
Tab("Tab1", systemImage: "gear", value: RootTab.tab1) {
NavigationStack(path: $appState.tab1Stack) {
Text("Tab 1 Stack")
NavigationLink("Item 1", value: Tab1Stack.item1)
.padding()
NavigationLink("Item 2", value: Tab1Stack.item2)
.padding()
.navigationDestination(for: Tab1Stack.self) { stack in
Text("Stack \(stack.rawValue)")
}
.navigationTitle("Tab1Stack")
}
}
}
.tabViewStyle(.sidebarAdaptable)
.onChange(of: appState.rootTab) { _, _ in
appState.homeStack.removeAll()
appState.tab1Stack.removeAll()
}
}
}
@MainActor
@Observable
class AppState {
var rootTab: RootTab = .home
var homeStack: [HomeStack] = []
var tab1Stack: [Tab1Stack] = []
}
enum RootTab: Hashable {
case home
case tab1
case tab2
}
enum HomeStack: String, Hashable {
case home
case item1
case item2
}
enum Tab1Stack: String, Hashable {
case home
case item1
case item2
}
Already filed a feedback in case this is a bug, but posting here in case I'm doing something wrong?
I'd like the search field to automatically be displayed with the keyboard up when the view appears. This sample code works in iOS 18, but it does not work in iOS 26 beta 7
I also tried adding a delay to setting searchIsFocused = true but that did not help
struct ContentView: View {
var body: some View {
NavigationStack {
NavigationLink(destination: ListView()) {
Label("Go to list", systemImage: "list.bullet")
}
}
.ignoresSafeArea()
}
}
struct ListView: View {
@State private var searchText: String = ""
@State private var searchIsPresented: Bool = false
@FocusState private var searchIsFocused: Bool
var body: some View {
ScrollView {
Text("Test")
}
.searchable(text: $searchText, isPresented: $searchIsPresented, placement: .automatic, prompt: "Search")
.searchFocused($searchIsFocused)
.onAppear {
searchIsFocused = true
}
}
}