Hi. The binding in a ForEach or List view doesn't work anymore when using the @Observable macro to create the observable object. For example, the following are the modifications I introduced to the Apple's example called "Migrating from the Observable Object Protocol to the Observable Macro" https://developer.apple.com/documentation/swiftui/migrating-from-the-observable-object-protocol-to-the-observable-macro
struct LibraryView: View {
@Environment(Library.self) private var library
var body: some View {
List($library.books) { $book in
BookView(book: book)
}
}
}
All I did was to add the $ to turn the reference to library.books into a binding but I got the error "Cannot find '$library' in scope"
Is this a bug or the procedure to use binding in lists changed?
Thanks
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
Any one getting any issues with NavigaitonLink to seemingly innocuous views freezing when tapped on? 1 CPU at 100% memory steadily increasing until app gets killed by the system. Will freeze if any NavigationLink on the view is tapped if certain views are linked to using NavigaitonLink.
I note some people have been getting similar freezes if they use @AppStorage, but I'm not using @AppStorage. I do use CoreData tho. tho I have some views that use core data that don't freeze.
https://developer.apple.com/forums/thread/708592?page=1#736374022
has anyone experienced similar issues? or know the cause. it doesn't seem to be any of my code because if I pause the debugger it stops on system code.
Hi,
I have added widgets to my iOS app and I would like to make this feature only accessible to "pro" users that have made a non-consumable in-app purchase.
Currently, I am doing the following: I store an "isUnlocked" property in the Keychain after the purchase is made
I read data to be displayed in the widget and here I also query the Keychain and store whether the widget is unlocked
I have no refresh policy, but only change the widget data on a significant time change
a different view is displayed when the app is locked
Some dummy code snippets:
func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> Void) {
		let entry = readContents()
		let timeline = Timeline(entries: [entry], policy: .never)
		completion(timeline)
}
struct WidgetEntryView: View {
		let entry: Provider.Entry
@Environment(\.widgetFamily) var family
@ViewBuilder
var body: some View {
switch family {
case .systemSmall:
if !entry.isUnlocked {
LockedWidgetView()
} else if let event = entry.event {
SmallWidgetEventView(event: event)
} else {
NoDataWidgetView()
}
...
func applicationSignificantTimeChange(_ application: UIApplication) {
		if #available(iOS 14.0, *) {
				WidgetCenter.shared.reloadAllTimelines()
		}
...
However, 2 unexpected things happen: the view is refreshed intraday (not only at midnight i.e. at significant time change)
sometimes the LockedWidgetView is displayed.
Especially the latter is problematic, because it gives false information to a user that has already made the in-app purchase.
How can I achieve my goal of only displaying info when the user has made the in-app purchase?
Thanks in advance.
P.S. Although it would not have my preference, I would also find it acceptable if the widget is only shown as option to add once the purchase is made. In other words, I was considering changing the Widget itself:
struct MyWidget: Widget {
private var supportedFamilies: [WidgetFamily] = isUnlocked() ? [.systemSmall, .systemMedium] : []
but I believe I cannot re-initialise the widget from the app when the user makes the in-app purchase, because the only refresh option that I have is
WidgetCenter.shared.reloadAllTimelines()
So I'm trying to use MapKit in a SwiftUI project targeting iOS/iPadOS. MapKit is obviously pretty limited in SwiftUI, but I've been getting warnings trying to set up basic annotations for the user to interact with.
When I use a basic MapMarker everything is fine (although it's hard to do anything with it), but whenever I do anything with MapAnnotation, I get this warning in Xcode (14.0.1) whenever I move the map around:
[SwiftUI] Publishing changes from within view updates is not allowed, this will cause undefined behavior.
I'm no SwiftUI expert, and I get how to fix this issue when binding in something like a sheet, but I don't see how what I'm doing with MapAnnotation should be causing this.
It looks like a bug to me, possibly complaining about the $region binding, but maybe I'm wrong? Am I doing something wrong or is this a bug?
Below is some sample code that reproduces this easily for me (just launch an app with the below code and then drag the map around to see the constant warnings in Xcode). It's mostly an example from here: https://www.hackingwithswift.com/books/ios-swiftui/integrating-mapkit-with-swiftui
import SwiftUI
import MapKit
struct Location: Identifiable {
let id = UUID()
let name: String
let coordinate: CLLocationCoordinate2D
}
struct ContentView: View {
@State private var region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 51.5, longitude: -0.12), span: MKCoordinateSpan(latitudeDelta: 0.2, longitudeDelta: 0.2))
let locations = [
Location(name: "Buckingham Palace", coordinate: CLLocationCoordinate2D(latitude: 51.501, longitude: -0.141)),
Location(name: "Tower of London", coordinate: CLLocationCoordinate2D(latitude: 51.508, longitude: -0.076))
]
var body: some View {
Map(coordinateRegion: $region, annotationItems: locations) { location in
MapAnnotation(coordinate: location.coordinate) {
Circle()
.stroke(.red, lineWidth: 3)
.frame(width: 44, height: 44)
}
}
.navigationTitle("Map")
.edgesIgnoringSafeArea(.all)
}
}
Hi,
In my apps, the recent iOS 16.0 beta 7 (20A5356a) broke the .timer DateStyle property of the Text view, in a SwiftUI widget.
In previous OS and beta, Text(Date(), style: .timer) was correctly displaying an increasing counter.
In iOS 6.0 beta 7, Text(Date(), style: .timer) does not update anymore, (and is offset to the left).
The other DateStyle (like .offset, .relative, ...) seems to update correctly.
Anyone noticed that (very specific) problem ?
I created a Radar for this FB14766095, but thought I would add it here for extra visibility, or if anyone else had any thoughts on the issue.
Basic Information
Please provide a descriptive title for your feedback:
iOS 18 hit testing functionality differs from iOS 17
What type of feedback are you reporting?
Incorrect/Unexpected Behavior
Description:
Please describe the issue and what steps we can take to reproduce it:
We have an issue in iOS 18 Beta 6 where hit testing functionality differs from the expected functionality in iOS 17.5.1 and previous versions of iOS.
iOS 17: When a sheet is presented, the hit-testing logic considers subviews of the root view, meaning the rootView itself is rarely the hit view.
iOS 18: When a sheet is presented, the hit-testing logic changes, sometimes considering the rootView itself as the hit view.
Code:
import SwiftUI
struct ContentView: View {
@State var isPresentingView: Bool = false
var body: some View {
VStack {
Text("View One")
Button {
isPresentingView.toggle()
} label: {
Text("Present View Two")
}
}
.padding()
.sheet(isPresented: $isPresentingView) {
ContentViewTwo()
}
}
}
#Preview {
ContentView()
}
struct ContentViewTwo: View {
@State var isPresentingView: Bool = false
var body: some View {
VStack {
Text("View Two")
}
.padding()
}
}
extension UIWindow {
public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
/// Get view from superclass.
guard let hitView = super.hitTest(point, with: event) else { return nil }
print("RPTEST rootViewController = ", rootViewController.hashValue)
print("RPTEST rootViewController?.view = ", rootViewController?.view.hashValue)
print("RPTEST hitView = ", hitView.hashValue)
if let rootView = rootViewController?.view {
print("RPTEST rootViewController's view memory address: \(Unmanaged.passUnretained(rootView).toOpaque())")
print("RPTEST hitView memory address: \(Unmanaged.passUnretained(hitView).toOpaque())")
print("RPTEST Are they equal? \(rootView == hitView)")
}
/// If the returned view is the `UIHostingController`'s view, ignore.
print("MTEST: hitTest rootViewController?.view == hitView", rootViewController?.view == hitView)
print("MTEST: -")
return hitView
}
}
Looking at the print statements from the provided sample project:
iOS 17 presenting a sheet from a button tap on the ContentView():
RPTEST rootViewController's view memory address: 0x0000000120009200
RPTEST hitView memory address: 0x000000011fd25000
RPTEST Are they equal? false
MTEST: hitTest rootViewController?.view == hitView false
RPTEST rootViewController's view memory address: 0x0000000120009200
RPTEST hitView memory address: 0x000000011fd25000
RPTEST Are they equal? false
MTEST: hitTest rootViewController?.view == hitView false
iOS 17 dismiss from presented view:
RPTEST rootViewController's view memory address: 0x0000000120009200
RPTEST hitView memory address: 0x000000011fe04080
RPTEST Are they equal? false
MTEST: hitTest rootViewController?.view == hitView false
RPTEST rootViewController's view memory address: 0x0000000120009200
RPTEST hitView memory address: 0x000000011fe04080
RPTEST Are they equal? false
MTEST: hitTest rootViewController?.view == hitView false
iOS 18 presenting a sheet from a button tap on the ContentView():
RPTEST rootViewController's view memory address: 0x000000010333e3c0
RPTEST hitView memory address: 0x0000000103342080
RPTEST Are they equal? false
MTEST: hitTest rootViewController?.view == hitView false
RPTEST rootViewController's view memory address: 0x000000010333e3c0
RPTEST hitView memory address: 0x000000010333e3c0
RPTEST Are they equal? true
MTEST: hitTest rootViewController?.view == hitView true
You can see here ☝️ that in iOS 18 the views have the same memory address on the second call and are evaluated to be the same. This differs from iOS 17.
iOS 18 dismiss
RPTEST rootViewController's view memory address: 0x000000010333e3c0
RPTEST hitView memory address: 0x0000000103e80000
RPTEST Are they equal? false
MTEST: hitTest rootViewController?.view == hitView false
RPTEST rootViewController's view memory address: 0x000000010333e3c0
RPTEST hitView memory address: 0x0000000103e80000
RPTEST Are they equal? false
MTEST: hitTest rootViewController?.view == hitView false
The question I want to ask:
Is this an intended change, meaning the current functionality in iOS 18 is expected?
Or is this a bug and it's something that needs to be fixed?
As a user, I would expect that the hit testing functionality would remain the same from iOS 17 to iOS 18.
Thank you for your time.
Hello Apple Community,
With a backend development background, I was always reluctant to do any front end. Especially with my bad experience with html & css, my negative opinion towards UI only got stronger.
When starting a new project at my current company, I was forced to do SwiftUI for iOS. After a few small (I mean really small) hiccups, I really understood the concept and it all became natural.
This positive experience made me want to try other front end frameworks which work for web. I dipped my toes into Jetpack Compose, C# UWP/WPF, Rust with EGUI.
I was really impressed with the performance and possibilities of Rust (EGUI) compiled to WASM. I was especially impressed that you do not have to use any HTML or CSS rather the rendering is completely up to you just like with a desktop application. I was always disappointed of the necessity of html, but with the rise of WASM in the recent years, I really hope there will be amazing alternatives using WASM & WEBGL.
Rust with EGUI is good and all but lets be honest to our self: With the ease of SwiftUI, its obvious why all the best looking applications are on iOS.
Its time for SwiftUI in web.
The advantages for the developers are obvious:
Arguably better UI Framework
No Html DOM stuff
Friendlier for new developers
One framework & language for multiple platforms
etc ...
But whats in for Apple? Why "waste" resources?
In my opinion the most important thing is: Increased Developer adoption
What is your opinion on this topic?
Would you use SwiftUI for web?
What are you currently using for web?
Do you prefer any other frontend framework over SwiftUI? (not considering the platform)
On iOS17, UIDevice.current.batteryLevel is returning values rounded to 0.05, such as 1, 0.95, 0.9. Which used to be a 1% granularity in iOS16. Is this a bug or a new feature?
Running up Xcode 16.2 Beta 1, a lot of my code that used onPreferenceChange in Views to change @State properties of those views, such as some notion of a measured width is now complaining about mutating the @MainActor-isolated properties from Sendable closures.
Now I've got to hoop-jump to change @State properties from onPreferenceChange? OK, but seems a bit of extra churn.
Hello,
I face an error everytime I want to interact with a TextField. The XCode debug area is showing :
CLIENT ERROR: TUINSRemoteViewController does not override -viewServiceDidTerminateWithError: and thus cannot react to catastrophic errors beyond logging them
There is no crash, and the text field is working fine.
I am developing for MacOS using a macbook pro Intel from 2019 with Sonoma 14.5 and Xcode 15.4 and I think that I noticed since the release of Sonoma. I was not particularly concerned by it but I noticed that interacting with the textField was leading to severe hang in my app, and micro-hang in the test app and I am wondering is these two issues could be related.
The message is easy to reproduce. Just create a new Project/Application/App using SwiftUI and add a TextField to the ContentView.
When you start app, click or double click on the text field, enter a message and press enter.
import SwiftUI
struct ContentView: View {
@State var value: String = ""
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
Text("Hello, world!")
TextField(text: $value,
label: {
Text("Test")
}
)
}
.padding()
}
}
Did you notice the same thing ? How I could solve it ?
Note : I already posted the problem on Swift forums but it was close because related to SwiftUI https://forums.swift.org/t/error-when-clicking-on-textfield-client-error-tuinsremoteviewcontroller-does-not-override-viewservicedidterminatewitherror-and-thus-cannot-react-to-catastrophic-errors-beyond-logging-them/72134/1
Thank you
There seems to be a performance issue when scrolling using the track pad with SwiftUI scroll views in macOS 15. This issue is NOT present in macOS 14.
When using the track pad the scrolling is not smooth, but "stutters". However scrolling using the scroll bars is very smooth. The "stuttering" is worse if the SwiftUI ScrollView is in the detail view of a NavigationSplitView.
The problem is not noticeable in scroll views with a small number views, but when the more views inside the scroll view, the more prominent the problem becomes.
I have a simple example app that illustrates the problem here (the example app is a simplification of my app Yammixer): https://github.com/danwaltin/SwiftUIScrollViewPerformance
When running this example app on macOS 14 (Sonoma) on an Intel i7 Mac book pro from 2019 the scrolling is "buttery smooth".
But on macOS 15 (Sequoia) on my Apple Silicon M1 Mac book pro the issue is very obvious.
When using Instruments I see that on macOS 15 "flame graph" shows that 85% of the execution time is in a "_hitTestForEvent" method. If the test app does not use NavigationSplitView about 70% of execution time is in the _hitTestForEvent method.
Topic:
UI Frameworks
SubTopic:
SwiftUI
Hello Dear Developers,
Is it only to me or in iOS 18 there's a problem with Settings.bundle, Im using my settings.bundle to set my enivement for my app but after upgrading to iOS 18 I can't see my Settings.Bundle in my settings iphone,
just to mention that I also updated my xcode to 16.
Anyone who has occur with this problem? :)
When I use the .zoom transition in a navigation stack, I get a glitch when interrupting the animation by swiping back before it completes.
When doing this, the source view disappears. I can still tap it to trigger the navigation again, but its not visible on screen.
This seems to be a regression in iOS 26, as it works as expected when testing on iOS 18.
Has someone else seen this issue and found a workaround? Is it possible to disable interrupting the transition?
Filed a feedback on the issue FB19601591
Screen recording:
https://share.icloud.com/photos/04cio3fEcbR6u64PAgxuS2CLQ
Example code
@State var showDetail = false
@Namespace var namespace
var body: some View {
NavigationStack {
ScrollView {
showDetailButton
}
.navigationTitle("Title")
.navigationBarTitleDisplayMode(.inline)
.navigationDestination(isPresented: $showDetail) {
Text("Detail")
.navigationTransition(.zoom(sourceID: "zoom", in: namespace))
}
}
}
var showDetailButton: some View {
Button {
showDetail = true
} label: {
Text("Show detail")
.padding()
.background(.green)
.matchedTransitionSource(id: "zoom", in: namespace)
}
}
}
Topic:
UI Frameworks
SubTopic:
SwiftUI
Hello,
I am encountering compatibility issues with older JavaScript frameworks, specifically Ext JS 4.0 and Sencha Touch 2.0, after upgrading to iOS 18.2 Beta. My application, which was working fine on previous versions of iOS, is now experiencing rendering issues, broken touch events, and performance degradation on WebKit in iOS 18.2.
The issues I’m seeing include:
Sencha Touch 2.0: The UI elements (like fields, and lists) are not interactive or showing their content properly. There also seems to be a delay in rendering touch events.
This seem to no longer work as expected with the updated WebKit engine in iOS 18.2 Beta.
My Questions:
Are there any known issues with legacy JavaScript frameworks like Ext JS 4.0 and Sencha Touch 2.0 on iOS 18.2 Beta? Specifically, do these frameworks rely on older DOM methods or JavaScript features that might be deprecated in the latest WebKit engine?
Has Apple officially deprecated any JavaScript features or DOM methods in WebKit that might be causing these issues? If so, are there recommended workarounds or updates to ensure compatibility with iOS 18.2?
Is there a way to enable legacy JavaScript features or fallback modes in iOS 18.2 ?
I would appreciate any guidance on this, as we are facing significant issues with our app’s performance and UI since upgrading to iOS 18.2.
Thank you!
Topic:
UI Frameworks
SubTopic:
General
When I build my app for iPad OS, either 26, or 18.5, as well as iOS on 16.5 from Xcode 26 with UIDesignRequiresCompatibility enabled my app is crashing as it loads the main UIViewController, a subclassed UITabBarController which is being loaded programatically from a Storyboard from another SplashScreen ViewController.
On i(Pad)OS 18.5 I get this error:
Thread 1: "Could not instantiate class named _TtGC5UIKit17UICoreHostingViewVCS_21ToolbarVisualProvider8RootView_ because no class named _TtGC5UIKit17UICoreHostingViewVCS_21ToolbarVisualProvider8RootView_ was found; the class needs to be defined in source code or linked in from a library (ensure the class is part of the correct target)"
On iPadOS 26 I get this error:
UIKitCore/UICoreHostingView.swift:54: Fatal error: init(coder:) has not been implemented
There is no issue building from Xcode 16.4, regardless of targeted i(Pad)OS.
Hello,
With iOS 18, when NavigationStack is in new TabView, with path parameter containing current navigation state is set, the navigation destination view is pushed twice.
See below with example that pushes twice on iOS 18 but is correct on iOS 17
@MainActor
class NavigationModel: ObservableObject {
static let shared = NavigationModel()
@Published var selectedTab: String
@Published var homePath: [Route]
@Published var testPath: [Route]
}
struct ContentView: View {
@StateObject private var navigationModel: NavigationModel = NavigationModel.shared
var body: some View {
TabView(selection: $navigationModel.selectedTab){
HomeView()
.tabItem {
Label("Home", systemImage: "house")
}
.tag("home")
TestView()
.tabItem {
Label("Test", systemImage: "circle")
}
.tag("test")
}
}
}
struct HomeView: View {
@StateObject private var navigationModel: NavigationModel = NavigationModel.shared
var body: some View {
NavigationStack(path: $navigationModel.homePath){
VStack{
Text("home")
NavigationLink(value: Route.test1("test1")){
Text("Go to test1")
}
}
.navigationDestination(for: Route.self){ route in
NavigationModelBuilder.findFinalDestination(route:route)
}
}
}
}
I don't what causes the issue because it works well on iOS 16 and iOS 17. I think the path is somehow reset but I don't why (maybe by the TabView ?)
Note that the bug only occurs with TabView.
Don't really know if it is a TabView bug or if it is on my side.
I filed a feedback with sample project FB14312064
unifieldFlexKeyboard[53102:24145174] [External] -[UIInputViewController needsInputModeSwitchKey] was called before a connection was established to the host application. This will produce an inaccurate result. Please make sure to call this after your primary view controller has been initialized.
hey
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")
}
}
}
}
}
I have a List in a sidebar style which contains a LazyVGrid and a Section with a simple list contents. Every thing works well except when content increases and layout changes (from two columns to one column) for the LazyVGrid with editMode changing to .active ... LazyVGrid does not expand/resize when the content increases (the increased content gets clipped)...but does when user expands/folds on the section below :(. However LazyVGrid resizes to show the entire content when the content shrinks with editMode reverting to .inactive
Note: If I replace the List with a ScrollView...lazyVGrid resizes perfectly when content increases in editMode = .active....but then I would lose all the Sidebar and List characteristics for the Section below :(
Also, looks like .onMove is not supported in LazyVGrids
Any pointers to solve the LazyVGrid (embedded in a List) not resizing or expanding when content increases ... will be deeply appreciated.
var body: some View {
List {
LazyVGrid(columns: editMode?.wrappedValue == .active ? singleColumn : twoColumns, alignment: .leading, spacing: 10) {
ForEach(editMode?.wrappedValue == .active ? allDashItems : selectedDashItems) { dashitem in
DashItemCell(dashitem)
}
.onMove(perform: moveDashItem)
.environment(\.editMode, editMode)
}
Section(header: Text("Bottom Section")) {
ForEach (sectionList)	{ item in
ListItemCell(item)
}
.onDelete(perform: deleteFolder)
.onMove(perform: moveFolder)
}
}
.listStyle(SidebarListStyle())
}
Hi all,
After upgrading to the iOS 26 beta, the scrolling in my SwiftUI chat view is completely broken. The exact same code works perfectly on iOS 18.
Context:
I have a chat view using ScrollViewReader and a vertically-reversed ScrollView (with .rotationEffect(.degrees(180))). Each message row (MessageBubble) uses multiple simultaneousGesture handlers:
Horizontal drag for swipe-to-reply (and other actions: pin, delete)
Long press for showing popover/actions
Vertical scroll for normal chat scrolling
This was working great on iOS 18. In iOS 26 beta, the vertical scroll is either completely disabled, jittery, or hijacked by the message row’s drag gestures, even though .simultaneousGesture is used (see code below).
Minimal Repro Sample
MessageListView.swift
swift
Copy
Edit
ScrollViewReader { proxy in
ScrollView(.vertical, showsIndicators: false) {
LazyVStack(spacing: 0) {
// ... grouped messages
ForEach(...) { ...
MessageBubble(...) // see below
}
Color.clear.frame(height: 8).id("BOTTOM_ANCHOR")
}
.padding(.horizontal, 4)
.rotationEffect(.degrees(180))
}
.rotationEffect(.degrees(180))
}
MessageBubble.swift
struct MessageBubble: View {
// ...
var body: some View {
// horizontal swipe-to-reply gesture
let dragGesture = DragGesture(minimumDistance: 10)
// ...
ZStack {
// ...
HStack { ... }
// ...
.simultaneousGesture(
DragGesture(minimumDistance: 0) // for long press
// ...
)
.simultaneousGesture(dragGesture) // for horizontal swipe
}
// ...
}
}