All of a sudden, after iOS 18.4 was released, I am having tons of navigation problems in my app in production. Buttons navigating to empty pages, views seeming to 'freeze', top navigation bar mismatched with the content of the page. It seems that iOS 18.4 broke a critical piece of UIKit + SwiftUI bridging functionality that my project relies on.
** Originally posted in 'Core OS' topic but realized 'UI Frameworks > General' made more sense. My bad. **
My application is written with both UIKit and SwiftUI components. Here is a breakdown of my setup:
UIApplicationDelegate >
UIWindow >
rootViewController of window is a UITabBarController >
each tab is a UINavigationController
rootViewController of nav controller is a UIHostingController >
rootView of the hosting controller is a SwiftUI View
In my SwiftUI views, I have been using NavigationLink for horizontal 'push' style navigation in my SwiftUI views. I do not use NavigationView, I only rely on the bridging capabilities of UINavigationController to action on my NavigationLinks. This has never been an issue, until iOS 18.4 was released. Now, when running iOS 18.4, I am having all sorts of unexpected behavior in the UI. I will break down 2 of these use cases here:
Use case A:
In one of my SwiftUI views, I have a ForEach for which each element's view is a NavigationLink. This is using the NavigationLink(_ destination:,label:) initializer. Navigating forward from here works/looks normal.
However, once I try to navigate backward from that destination (tap the 'Back' button in top left), the view goes blank and the navigation bar at the top of the page (which is maintained by the UINavigationController instance) does not change. If I call popToRootViewController on that nav controller, the navigation bar at the top of the page returns to its normal state, but the view is still blank.
It is not until after I have called popToRootViewController, and then navigate to a different tab of the UITabBarController and return to the initial tab, does the SwiftuI content view (the one with the ForEach) finally redraw and the view hierarchy is restored.
Here is a warning that is logged in the console when I tap the 'Back ' button:
Top view controller's view unexpectedly not in window for navigation transition. Skipping layout. nav = <UINavigationController: 0x1110bbe00>, topVC = <TtGC7SwiftUI19UIHostingControllerV5MyApp10MyPage: 0x106814e00>
EDIT: If I replace the NavigationLink with a call to UINavigationController.pushViewController, I am still seeing the exact same behavior. Pressing back button makes the view empty > need to pop to root view controller and switch tabs in order to restore the view.
Use case B
Another instance of this issue happens whenever I try to use a NavigationLink inside of a view that itself was the destination of a NavigationLink in its parent view (i.e.: Root view > detail view > sub-detail view). For example, take the detail view destination in use case A. I have tapped a NavigationLink from the ForEach and landed on the detail view. Again, so far things work/look normal. Now, if I tap on another NavigationLink from that detail view, the view does not transition to the new page. The top navigation bar does transition, and shows the title and actions associated with this second destination. However, the view of this second destination is not displayed.
It is worth noting that the same warning I mentioned above is also logged when I tap the NavigationLink to navigate to this second destination.
Top view controller's view unexpectedly not in window for navigation transition. Skipping layout. nav = <UINavigationController: 0x109859400>, topVC = <TtGC7SwiftUI19UIHostingControllerVVS_19BridgedPresentation8RootView: 0x300ab8000>
Strangely, if I switch to a different tab of the UITabBarController and back to the initial tab, this second destination's view is successfully rendered. It seems that switching tabs in this UITabBarController is calling something in either SwiftUI or UIKit that is redrawing my views.
Conclusion
This is a serious issue with UIKit + SwiftUI bridging support. I have never had problems like this until devices started running iOS 18.4, and there is nothing in the iOS 18.4 changelog that suggests this was an intentional change. All of a sudden, after updating to the latest iOS version, my app is totally broken.
I want to be clear that I'm not using deprecated NavigationLink methods in these instances. My app's minimum deployment target is iOS 16.
I know that there are more modern navigation APIs like navigation stack, etc. I am looking for answers about my use case: whether it is officially unsupported as of iOS 18.4, whether this setup should be supported and this is indeed some sort of bug in iOS, or anything in-between. I'm happy to provide formatted code if needed for discussion purposes. This is about my entire app's view hierarchy so there are a lot of disparate lines of code that make up this problem.
Explore the various UI frameworks available for building app interfaces. Discuss the use cases for different frameworks, share best practices, and get help with specific framework-related questions.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
On iOS 18, while on a modal screen, if the scrolling starts on a button, that button gets pressed, outside of a modal this doesn't reproduce, also not reproducible on older iOS versions, neither on modals or outside of them.
The code to reproduce the issue:
import SwiftUI
struct ContentView: View {
@State var presentModal = false
var body: some View {
Button(action: {
presentModal = true
}, label: {
Text("open modal")
})
.sheet(isPresented: $presentModal, content: {
ScrollView {
ForEach(0..<100, id: \.self) { index in
Button(action: {
print("Button \(index) tapped!")
}) {
Text("Button \(index)")
.frame(maxWidth: .infinity)
.frame(height: 100)
.background(randomColor(for: index))
.padding(.horizontal)
}
}
}
})
}
func randomColor(for index: Int) -> Color {
let hue = Double(index % 100) / 100.0
return Color(hue: hue, saturation: 0.8, brightness: 0.8)
}
}
#Preview {
ContentView()
}
I found an issue when implementing an alert with a TextField to input a name. I want the action button to be disabled until a name has been entered, but the action block is never executed when the button has become enabled and pressed. The problem seems to appear only when name is initially an empty string. Tested with iOS 17.0.
struct MyView: View {
@State private var name = ""
var body: some View {
SomeView()
.alert(...) {
TextField("Name", text: $name)
Button("Action") {
// Action
}.disabled(name.isEmpty)
Button("Cancel", role: .cancel) {}
}
}
}
In my visionOS app, I'm seeing this error in the console dozens of times. Anyone know what it means, or how to troubleshoot it?
Searching these forums and the usual other places hasn't come up with anything that seems relevant.
Hi, I faced with the issue on iOS 26.1 with PHPickerViewController. After first selection I save assetIdentifier of PHPickerResult for images.
next time I open the picker I expect to have the images selected based on assetIdentifier
Code:
var config = PHPickerConfiguration(photoLibrary: .shared())
config.selectionLimit = 10
config.filter = .images
config.preselectedAssetIdentifiers = images.compactMap(\.assetID)
let picker = PHPickerViewController(configuration: config)
picker.delegate = self
present(picker, animated: true)
But on iOS 26.1 they aren't selected. On lower iOS version all works fine.
Does anybody faced with similar issue?
Topic:
UI Frameworks
SubTopic:
UIKit
Our app was just rejected by Apple because they say the subscription management sheet never loads. It just spins indefinitely.
We're using StoreKit's manageSubscriptionsSheet view modifier to present the sheet, and it's always worked for us when testing in SandBox.
Has anyone else had this problem?
Given that it's Apple's own code that got us rejected, what's our path forward?
Filed in Feedback as FB20772137
Zoom transition originating from inside tabViewBottomAccessory, when the binding passed to fullScreenCover's item is a Binding other than a "$-synthesized" binding, the animation fails with the following error (and crucially fails to perform the desired animation):
Starting a zoom transition from a nil view will trigger a fallback transition. To get the best possible teansition, be sure to provide a view that's visible and in a window.
What I want to do is pass a binding to a property inside an ObservableObject (or @Observable, but it doesn't matter) to hold the item representing the presentation. But this stopped working as of 26.1b4. It worked in 26.1b3 and in 26.0 (and 26.0.1)
Here's the gist of code that will reproduce the issue (I've omitted irrelevant details in the interest of brevity):
struct ContentView: View {
@Binding var presentation: PresentationDestination?
@Namespace private var animation
var body: some View {
// Omitted TabView stuff…
.tabViewBottomAccessory {
miniPlayer
.matchedTransitionSource(
id: "player",
in: animation
)
}
.fullScreenCover(
item: $presentation,
content: { _ in
fullScreenPlayer
.navigationTransition(
.zoom(
sourceID: "player",
in: animation
)
)
})
}
As you can see, ContentView takes a Binding to the presentation, but it matters how this binding is constructed.
This works:
@State private var presentation: PresentationDestination
…
ContentView(presentation: $presentation)
This fails (as does ObservableObject with @Published):
@Observable
class Router2 {
var presentation: PresentationDestination?
}
…
@State private var router2 = Router2()
…
ContentView(presentation: $router2.presentation)
Also, this fails:
@State private var presentation: PresentationDestination
…
ContentView(
presentation: .init(get: {
presentation
}, set: { newValue in
presentation = newValue
})
)
These differences are unexpected, of course. I consider this a regression in 26.1b4
I should add that if I move the source of the transition to somewhere outside tabViewBottomAccessory things seem to work fine.
When integrating the Automatic Sign-In API on physical devices (iPhone SE with iOS 26.0 and Apple TV with tvOS 26.0), the call to requestAutoSignInAuthorization() results in an immediate error stating "Service temporarily unavailable." This prevents the app from obtaining the necessary authorization context to proceed with token updates and the Automatic Sign-In flow.
The issue occurs specifically at the authorization request stage and does not progress to calling updateAutoSignInToken(), since it does not acquire conditions for it. All entitlement and sandbox setup have been verified and are correctly configured.
Error:
Error Domain=VSErrorDomain Code=3 "The service is temporarily unavailable." UserInfo={NSLocalizedDescription=The service is temporarily unavailable., NSLocalizedRecoverySuggestion=Please try again later.}
Topic:
UI Frameworks
SubTopic:
General
In beta 2 using layer.cornerRadius on a UIEffectView with the UIGlassEffect allowed you to change the corner radius of the view. In beta 3, this no longer works. WWDC videos indicate the right way to do this is to set the cornerConfiguration on the UIEffectView, but that API doesn't seem to be available yet. At this time it doesn't seem like theres a way to have a glass view that isn't pill shaped.
Hi! When building my app using Xcode 16, fast scrolling (using scrollViewProxy.scrollTo) a list would result in items not appearing even when scrolling stopped. This does not happen when the app is built with Xcode 15, even on iOS 18.
I'm also getting this error in the logs: List failed to visit cell content, returning an empty cell. - SwiftUICore/Logging.swift:84 - please file a bug report.
I have a few view controllers in a large UIKit application that previously started showing content right below the bottom of the top navigation toolbar.
When testing the same code on iOS 26, these same views have their content extend under the navigation bar and toolbar. I was able to fix it with:
if #available(iOS 26, *, *) {
self.edgesForExtendedLayout = [.bottom]
}
when running on iOS 26. I also fixed one or two places where the main view was anchored to self.view.topAnchor instead of self.view.safeAreaLayoutGuide.topAnchor.
Although this seems to work, I wonder if this was an intended change in iOS 26 or just a temporary bug in the beta that will be resolved.
Were changes made to the safe area and edgesForExtendedLayout logic in iOS 26? If so, is there a place I can see what the specific changes were, so I know my code is handling it properly?
Thanks!
Topic:
UI Frameworks
SubTopic:
UIKit
I have a simple example to demonstrate...
struct MyView: View {
var body: some View {
Text("WOW")
}
}
struct MyOtherView: View {
var body: some View {
NavigationStack {
Text("WOW")
}
}
}
On VisionOS, MyOtherView has a glass background effect that cannot be disabled. glassBackgroundEffect(displayMode: .never) .background(.clear), .foregroundColor(.clear), none of them work.
I then resorted to the SwiftUIIntrospect package to try set .clear on various child objects of the NavigationStack but nothing is working.
I am in control of my own glass containers. I have a couple with space between them, but with the NavigationStack it sets a background behind both of them ruining the effect.
This is what MyOtherView renders as:
I'm looking for it to be completely transparent except the text. Like the below layout.
For now I will have to roll my own navigation.
Since iOS 18.3, icons are no longer generated correctly with QLThumbnailGenerator.
No error is returned either.
But this error message now appears in the console:
Error returned from iconservicesagent image request: <ISTypeIcon: 0x3010f91a0>,Type: com.adobe.pdf - <ISImageDescriptor: 0x302f188c0> - (36.00, 36.00)@3x v:1 l:5 a:0:0:0:0 t:() b:0 s:2 ps:0 digest: B19540FD-0449-3E89-AC50-38F92F9760FE error: Error Domain=NSOSStatusErrorDomain Code=-609 "Client is disallowed from making such an icon request" UserInfo={NSLocalizedDescription=Client is disallowed from making such an icon request}
Does anyone know this error? Is there a workaround?
Are there new permissions to consider?
Here is the code how icons are generated:
let request = QLThumbnailGenerator.Request(fileAt: url, size: size, scale: scale, representationTypes: self.thumbnailType)
request.iconMode = true
let generator = QLThumbnailGenerator.shared
generator.generateRepresentations(for: request) { [weak self] thumbnail, _, error in
}
In WWDC25 video 284: Build a UIKit app with the new design, there is mention of a cornerConfiguration property on UIVisualEffectView. But this properly isn't documented and Xcode 26 isn't aware of any such property.
I'm trying to replicate the results of that video in the section titled Custom Elements starting at the 19:15 point. There is a lot of missing details and typos in the code associated with that video.
My attempts with UIGlassEffect and UIViewEffectView do not result in any capsule shapes. I just get rectangles with no rounded corners at all.
As an experiment, I am trying to recreate the capsule with the layers/location buttons in the iOS 26 version of the Maps app.
I put the following code in a view controller's viewDidLoad method
let imgCfgLayer = UIImage.SymbolConfiguration(hierarchicalColor: .systemGray)
let imgLayer = UIImage(systemName: "square.2.layers.3d.fill", withConfiguration: imgCfgLayer)
var cfgLayer = UIButton.Configuration.plain()
cfgLayer.image = imgLayer
let btnLayer = UIButton(configuration: cfgLayer, primaryAction: UIAction(handler: { _ in
print("layer")
}))
var cfgLoc = UIButton.Configuration.plain()
let imgLoc = UIImage(systemName: "location")
cfgLoc.image = imgLoc
let btnLoc = UIButton(configuration: cfgLoc, primaryAction: UIAction(handler: { _ in
print("location")
}))
let bgEffect = UIGlassEffect()
bgEffect.isInteractive = true
let bg = UIVisualEffectView(effect: bgEffect)
bg.contentView.addSubview(btnLayer)
bg.contentView.addSubview(btnLoc)
view.addSubview(bg)
btnLayer.translatesAutoresizingMaskIntoConstraints = false
btnLoc.translatesAutoresizingMaskIntoConstraints = false
bg.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
btnLayer.leadingAnchor.constraint(equalTo: bg.contentView.leadingAnchor),
btnLayer.trailingAnchor.constraint(equalTo: bg.contentView.trailingAnchor),
btnLayer.topAnchor.constraint(equalTo: bg.contentView.topAnchor),
btnLoc.centerXAnchor.constraint(equalTo: bg.contentView.centerXAnchor),
btnLoc.topAnchor.constraint(equalTo: btnLayer.bottomAnchor, constant: 15),
btnLoc.bottomAnchor.constraint(equalTo: bg.contentView.bottomAnchor),
bg.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor),
bg.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 40),
])
The result is pretty close other than the complete lack of capsule shape.
What changes would be needed to get the capsule shape? Is this even the proper approach?
Prior to iOS 26, it was possible to design an inputAccessoryView(Controller) that would integrate seamlessly with the system keyboard, by which I mean appearing as a natural extension of the system keyboard. For example, using CYRKeyboardButton https://github.com/tmcintos/CYRKeyboardButton.
To date, I have successfully used this to provide an enhanced numeric key row within my apps, which is a distinguishing feature of these apps. It took a lot of engineering and testing effort to perfect this design. However, with iOS 26 the design is completely broken due to the system keyboard UI change, which makes it impossible to display an inputAccessoryView seamlessly along the top of the system keyboard (see attached screenshots).
In my opinion, it is just plain reckless for Apple to make these kinds of trivial UI changes, which break existing app designs without adding any significant value to the user experience.
iOS ≤ 18.x:
iOS 26 beta:
Hey,
The new "soft" scroll edge effect is really cool! But it seems to only appear when you add toolbar items.
Is there a way to add it for "custom" views as well, that I place in a safe area inset?
For example, the messages app in iOS 26 does this. There's a text field as a safe area inset as well as a soft scroll edge effect.
Thanks!
Environment
iOS 26 (23A343)
Xcode 26
Reproduces on device and Simulator
Description
When presenting a SwiftUI WebView (native iOS 26 component) or a WKWebView/UIWebView via UIViewRepresentable, focusing a text field inside the web view and then dismissing it breaks the keyboard layout behavior.
After returning to the main app, tapping any TextField causes the keyboard to cover bottom controls (e.g. buttons). Expected safe area insets are not applied.
The issue is only resolved after closing and reopening the keyboard once.
Steps to Reproduce
Open a SwiftUI screen with WebView (via .sheet or NavigationLink).
Inside the web view, tap a text field to show the keyboard.
Dismiss the web view.
Tap a TextField in the main app.
Expected Result
Layout should adjust correctly.
Bottom controls stay visible above the keyboard.
Actual Result
Keyboard covers bottom controls.
Insets are ignored until the keyboard is dismissed and reopened.
Notes
Reproduces with:
Native SwiftUI WebView (iOS 26)
WKWebView and UIWebView via UIViewRepresentable
Presentation style (.sheet or navigation push) does not matter.
Example video: https://youtu.be/Epgoz1vETKU
FB: FB20386257
Sample Code
import SwiftUI
import WebKit
struct ContentView: View {
@State var url: URL?
@FocusState private var isFocused: Bool
var body: some View {
VStack {
TextField("TextField", text: .constant(""))
.focused($isFocused)
Button("HIDE KEYBOARD") { isFocused = false }
Spacer()
Button("ACTION") {
url = URL(string: "https://google.com")
}
}
.sheet(item: $url) { value in
NavigationStack {
WebView(url: value)
.toolbar {
ToolbarItem(placement: .topBarLeading) {
Button("CLOSE") { url = nil }
}
}
}
}
}
}
extension URL: Identifiable {
public var id: String { absoluteString }
}
Try this simple code:
import SwiftUI
import StoreKit
struct ReviewView: View {
@Environment(\.requestReview) var requestReview
var body: some View {
Button("Leave a review") {
requestReview()
}
}
}
When the Review Alert shows, the "Not Now" button is disabled for some reason!? It was always tappable in all iOS versions that I remember. And there is no way to opt out, unless the user taps on the stars first. Is it a bug or a feature?
Thanks for looking into it!
Hi,
I've run into two problems using SwiftData in iOS 18 that are total show-stoppers for my app, causing it to run out of memory and be killed by the system. The same app runs fine on iOS 17.
The two problems are inter-related in a way I can't exactly diagnose, but are easy to reproduce.
Problem #1: Calling .count on the array that represents a relationship or Query causes the whole array of objects to be loaded into memory.
Problem #2: When a @Model object is loaded, properties that are declared with .externalStorage are loaded unnecessarily, and use tons of memory.
It's possible that #1 is normal behavior, exacerbated by #2.
I've written a test app that demonstrates the extreme difference in memory usage between the OS Versions. It uses a typical navigation pattern, with content counts on the left-side view. Each item has one thumbnail and one large image in .externalStorge. GitHub Source
When populated with 80 items, each containing one thumbnail and one large image in .externalStorge, the app launches in 17.5 using 29mb of memory. On iOS 18, in the same conditions, 592 mb.
When the first folder is selected, causing a list of thumbnails to load, iOS 17 uses just 86mb. iOS 18 uses 599mb, implying that all image data has already been loaded.
So I'm asking for help from Apple or the Community in finding a workaround. I've been advised that finding a workaround may be necessary, as this may not be addressed in 18.0.
Thanks in advance for any insight.
Radars: FB14323833, FB14323934
(See attached images, or try it yourself)
(You may notice in the 18.0 screenshots that the item counts don't add up right. That's yet another 18.0-SwiftData anomaly regarding relationships that I haven't tackled yet, but is also demonstrated by the sample app.)
The following WatchOs App example is very short, but already not functioning as it is expected, when using Digital Crown (full code):
import SwiftUI
struct ContentView: View {
let array = ["One","Two","Three","Four"]
@State var selection = "One"
var body: some View {
Picker("Array", selection: $selection) {
ForEach(array, id: \.self) {
Text($0)
}
}
}
}
The following 2 errors are thrown, when using Digital Crown for scrolling:
ScrollView contentOffset binding has been read; this will cause grossly inefficient view performance as the ScrollView's content will be updated whenever its contentOffset changes. Read the contentOffset binding in a view that is not parented between the creator of the binding and the ScrollView to avoid this.
Error: Error Domain=NSOSStatusErrorDomain Code=-536870187 "(null)"
Any help appreciated. Thanks a lot.