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.

All subtopics
Posts under UI Frameworks topic

Post

Replies

Boosts

Views

Activity

UIAlertController sometimes does not call its UIAlertAction handler
The iOS app that I’m helping to develop displays the following behavior, observed on an iPad Pro (4th generation) running iOS 18.1.1: The app uses UIAlertController to show an action sheet with two buttons (defined by two UIAlertAction objects). Each button has a handler block, and the first thing each handler does is to log that it was called. When the user taps one of the buttons and the action sheet disappears, most of the time the appropriate UIAlertAction handler is called. But sometimes there is no log entry for either of the action handlers, nor does the app do anything else associated with the chosen button, in which case I conclude that the handler was not called. I want to emphasize that I’m describing instances of the same action sheet displayed by the same code. Most of the time the appropriate button handler is called, but sometimes the handler is not called. The uncalled handler problem occurs about once per hour during normal use of the app. The problem has continued to occur across many weeks of testing. What could cause UIAlertController not to call its action handler?
Topic: UI Frameworks SubTopic: UIKit Tags:
6
0
146
Apr ’25
Why my app clips is Unavailable
My App Clip is associated with three domains: • nfc.ttwifi.net • qr.ttwifi.net Currently, I’m experiencing an issue where scanning a QR code from qr.ttwifi.net correctly launches my App Clip. However, when I scan a QR code from nfc.ttwifi.net, it successfully displays the App Clip card but then shows the message “App Clip unavailable.” I checked the Website Status in App Store Connect, and both domains have their Debugging Status and Cache Status marked as Verified. One important detail to note: Yesterday, while submitting a new version for review, I noticed that nfc.ttwifi.net showed “Unable to connect to AASA file” in the Cache Status in App Store Connect. The cache status update time was March 27, 2025, at 6:52 PM. However, when I checked today, both domains appeared to be fine, and the cache status update time was March 27, 2025, at 7:07 PM. How can I restore the App Clip functionality for my nfc.ttwifi.net domain?
6
0
240
Apr ’25
Change tint of back button in UINavigationItem on iOS 26
I am struggling to change the tint of the back button in an UINavigationItem. In iOS 18.6 it looks like this while on iOS 26 the same looks like this I can live without the Dictionary but I'd like to get the blue color back. In viewDidLoad() I have tried navigationItem.backBarButtonItem?.tintColor = .link but this did not work since navigationItem.backBarButtonItem is nil. My second attempt was navigationController?.navigationBar.tintColor = .link but this didn't work either. I have even set the Global Tint to Link Color but this had no effect either. Does anyone have an idea how to change the tint of the back button in an UINavigationItem on iOS 26?
Topic: UI Frameworks SubTopic: UIKit Tags:
6
1
447
Jan ’26
Swift Charts: How to prevent scroll position jump when loading more data dynamically
I'm implementing infinite scrolling with Swift Charts where additional historical data loads when scrolling near the beginning of the dataset. However, when new data is loaded, the chart's scroll position jumps unexpectedly. Current behavior: Initially loads 10 data points, displaying the latest 5 When scrolling backwards with only 3 points remaining off-screen, triggers loading of 10 more historical points After loading, the scroll position jumps to the 3rd position of the new dataset instead of maintaining the current view Expected behavior: Scroll position should remain stable when new data is loaded User's current view should not change during data loading Here's my implementation logic using some mock data: import SwiftUI import Charts struct DataPoint: Identifiable { let id = UUID() let date: Date let value: Double } class ChartViewModel: ObservableObject { @Published var dataPoints: [DataPoint] = [] private var isLoading = false init() { loadMoreData() } func loadMoreData() { guard !isLoading else { return } isLoading = true let newData = self.generateDataPoints( endDate: self.dataPoints.first?.date ?? Date(), count: 10 ) self.dataPoints.insert(contentsOf: newData, at: 0) self.isLoading = false print("\(dataPoints.count) data points.") } private func generateDataPoints(endDate: Date, count: Int) -> [DataPoint] { var points: [DataPoint] = [] let calendar = Calendar.current for i in 0..<count { let date = calendar.date( byAdding: .day, value: -i, to: endDate ) ?? endDate let value = Double.random(in: 0...100) points.append(DataPoint(date: date, value: value)) } return points.sorted { $0.date < $1.date } } } struct ScrollableChart: View { @StateObject private var viewModel = ChartViewModel() @State private var scrollPosition: Date @State private var scrollDebounceTask: Task<Void, Never>? init() { self.scrollPosition = .now.addingTimeInterval(-4*24*3600) } var body: some View { Chart(viewModel.dataPoints) { point in BarMark( x: .value("Time", point.date, unit: .day), y: .value("Value", point.value) ) } .chartScrollableAxes(.horizontal) .chartXVisibleDomain(length: 5 * 24 * 3600) .chartScrollPosition(x: $scrollPosition) .chartXScale(domain: .automatic(includesZero: false)) .frame(height: 300) .onChange(of: scrollPosition) { oldPosition, newPosition in scrollDebounceTask?.cancel() scrollDebounceTask = Task { try? await Task.sleep(for: .milliseconds(300)) if !Task.isCancelled { checkAndLoadMoreData(currentPosition: newPosition) } } } } private func checkAndLoadMoreData(currentPosition: Date?) { guard let currentPosition, let earliestDataPoint = viewModel.dataPoints.first?.date else { return } let timeInterval = currentPosition.timeIntervalSince(earliestDataPoint) if timeInterval <= 3 * 24 * 3600 { viewModel.loadMoreData() } } } I attempted to compensate for this jump by adding: scrollPosition = scrollPosition.addingTimeInterval(10 * 24 * 3600) after viewModel.loadMoreData(). However, this caused the chart to jump in the opposite direction by 10 days, rather than maintaining the current position. What's the problem with my code and how to fix it?
6
0
593
Jun ’25
SwiftData document based on iOS18 shows blank screen
I have some apps using SwiftData document based. They work as expected under iOS17, but not under iOS18: install the app on a iPad 11 pro (first gen) from my MacBook open the app and open an existing fils (perfect under iOS17) it shows a blank, white screen, no data I can create a new document, blank screen, no data When I open that newly created file on a iOS 17 iPad pro, it works perfect, as expected The apps were created from scratch under macOS 14.7 with the corresponding Xcode/Swift/UI version. iOS devices under iOS17 Are there any known problems with document based SwiftData-apps under iOS18, are there any changes one has to made? Thank You so much for any help!
6
0
796
Apr ’25
Cannot get drop action to trigger (Xcode 26 beta 3)
I'm unable to find the right combination modifiers to get drag and drop to work using the new .draggable(containerItemID:) and dragContainer(for:in:selection:_:) modifiers. The drag is initiated with the item's ID, the item is requested from the .dragContainer modifier, but the drop closure is never triggered. Minimal repro: struct Item: Identifiable, Codable, Transferable { var id = UUID() var value: String static var transferRepresentation: some TransferRepresentation { CodableRepresentation(contentType: .tab) } } struct DragDrop: View { @State var items: [Item] = [ Item(value: "Hello"), Item(value: "world"), Item(value: "something"), Item(value: "else") ] var body: some View { List(items) { item in HStack { Text(item.value) Spacer() } .contentShape(Rectangle()) .draggable(containerItemID: item.id) .dropDestination(for: Item.self) { items, session in print("Drop: \(items)") } } .dragContainer(for: Item.self) { itemID in print("Drag: \(itemID)") return items.filter { itemID == $0.id } } } } #Preview("Simple") { DragDrop() }
6
0
154
Jul ’25
Insight into BaseBoard/FrontBoardServices Crashes Needed
We're seeing a sharp uptick in BaseBoard/FrontBoardServices crashes since we migrated from UIApplicationDelegate to UIWindowSceneDelegate. Having exhausted everything on my end short of reverse engineering BaseBoard or making changes without being able to know if they work, I need help. I think all I need to get unstuck is an answer to these questions, if possible: What does -[BSSettings initWithSettings:] enumerate over? If I know what's being enumerated, I'll know what to look for in our app. What triggers FrontBoardServices to do this update? If I can reproduce the crash--or at least better understand when it may happen--I will be better able to fix it Here's two similar stack traces: App_(iOS)-crashreport-07-30-2025_1040-0600-redacted.crash App_(iOS)-crashreport-07-30-2025_1045-0600-redacted.crash Since these are private trameworks, there is no documentation or information on their behavior that I can find. There are other forum posts regarding this crash, on here and on other sites. However, I did not find any that shed any insight on the cause or conditions of the crash. Additionally, this is on iPhone, not macOS, and not iPad. This post is different, because I'm asking specific questions that can be answered by someone with familiarity on how these internal frameworks work. I'm not asking for help debugging my application, though I'd gladly take any suggestions/tips! Here's the long version, in case anyone finds it useful: In our application, we have seen a sharp rise in crashes in BaseBoard and FrontBoardServices, which are internal iOS frameworks, since we migrated our app to use UIWindowSceneDelegate. We were using exclusively UIApplicationDelegate before. The stack traces haven't proven very useful yet, because we haven't been able to reproduce the crashes ourselves. Upon searching online, we have learned that Baseboard/Frontsoardservices are probably copying scene settings upon something in the scene changing. Based on our crash reports, we know that most of our users are on an iPhone, not an iPad or macOS, so we can rule out split screen or window resizing. Our app is locked to portrait as well, so we can also rule out orientation changes. And considering the stack trace is in the middle of an objc_retain_x2 call, which is itself inside of a collection enumeration, we are assuming that whatever is being enumerated probably was changed or deallocated during enumeration. Sometimes it's objc_retain_x2, and sometimes it's a release call. And sometimes it's a completely different stack trace, but still within BaseBoard/FrontBoardServices. I suspect these all share the same cause. Because it's thread 0 that crashed, we know that BaseBoard/FrontBoardServices were running on the main thread, which means that for this crash to occur, something might be changing on a background thread. This is what leads me to suspect a race condition. There are many places in our app where we accidentally update the UI from a background thread. We've fixed many of them, but I'm sure there are more. Our app is large. Because of this, I think background UI are the most likely cause. However, since I can't reproduce the crash, and because none of our stack traces clearly show UI updates happening on another thread at the same time, I am not certain. And here's the stack trace inline, in case the attachments expire or search engines can't read them: Thread 0 name: Thread 0 Crashed: objc_retain_x2 (libobjc.A.dylib) BSIntegerMapEnumerateWithBlock (BaseBoard) -[BSSettings initWithSettings:] (BaseBoard) -[BSKeyedSettings initWithSettings:] (BaseBoard) -[FBSSettings _settings:] (FrontBoardServices) -[FBSSettings _settings] (FrontBoardServices) -[FBSSettingsDiff applyToMutableSettings:] (FrontBoardServices) -[FBSSettingsDiff settingsByApplyingToMutableCopyOfSettings:] (FrontBoardServices) -[FBSSceneSettingsDiff settingsByApplyingToMutableCopyOfSettings:] (FrontBoardServices) -[FBSScene updater:didUpdateSettings:withDiff:transitionContext:completion:] (FrontBoardServices) __94-[FBSWorkspaceScenesClient _queue_updateScene:withSettings:diff:transitionContext:completion:]_block_invoke_2 (FrontBoardServices) -[FBSWorkspace _calloutQueue_executeCalloutFromSource:withBlock:] (FrontBoardServices) __94-[FBSWorkspaceScenesClient _queue_updateScene:withSettings:diff:transitionContext:completion:]_block_invoke.cold.1 (FrontBoardServices) __94-[FBSWorkspaceScenesClient _queue_updateScene:withSettings:diff:transitionContext:completion:]_block_invoke (FrontBoardServices) _dispatch_client_callout (libdispatch.dylib) _dispatch_block_invoke_direct (libdispatch.dylib) __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ (FrontBoardServices) -[FBSMainRunLoopSerialQueue _targetQueue_performNextIfPossible] (FrontBoardServices) -[FBSMainRunLoopSerialQueue _performNextFromRunLoopSource] (FrontBoardServices) __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ (CoreFoundation) __CFRunLoopDoSource0 (CoreFoundation) __CFRunLoopDoSources0 (CoreFoundation) __CFRunLoopRun (CoreFoundation) CFRunLoopRunSpecific (CoreFoundation) GSEventRunModal (GraphicsServices) -[UIApplication _run] (UIKitCore) UIApplicationMain (UIKitCore) (null) (UIKitCore) main (AppDelegate.swift:0) 0x1ab8cbf08 + 0
Topic: UI Frameworks SubTopic: General Tags:
6
4
301
Jan ’26
Detecting marked range in UI/NSTextViews at the time of shouldChangeTextIn
We have submitted a feedback for this issue: FB21230723 We're building a note-taking app for iOS and macOS that uses both UITextView and NSTextView. When performing text input that involves a marked range (such as Japanese input) in a UITextView or NSTextView with a UITextViewDelegate or NSTextViewDelegate set, the text view's marked range (markedTextRange / markedRange()) has not yet been updated at the moment when shouldChangeTextIn is invoked. UITextViewDelegate.textView(_:shouldChangeTextIn:replacementText:) NSTextViewDelegate.textView(_:shouldChangeTextIn:replacementString:) The current behavior is this when entering text in Japanese: (same for NSTextView) func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { print(textView.markedTextRange != nil) // prints out false DispatchQueue.main.async { print(textView.markedTextRange != nil) // prints out true } } However, we need the value of markedTextRange right away in order to determine whether to return true or false from this method. Is there any workaround for this issue?
6
0
507
Jan ’26
ios26 NumberPad keyboard issue on iPad
On an iPad running iOS26, there is an issue with the numberPad keyboard I have a UITextField with a keyboard type of .numberPad When I first tap in the field, a new number pad with just numbers (similar to the one that shows up on iPhone) shows up. When I tap again in the field, that number pad goes away. When I tap in the field again, the full keyboard with numbers etc shows up (this is the one that used to always show up pre-iOS26)
Topic: UI Frameworks SubTopic: UIKit
6
2
942
Jan ’26
SwiftUI @State Updates Not Reflecting in UI Until View Reconstruction (Xcode Preview & Device)
Issue Description I'm experiencing a bizarre SwiftUI state update issue that only occurs in Xcode development environment (both Canvas preview and device debugging), but does not occur in production builds downloaded from App Store. Symptom: User taps a button that modifies a @State variable inside a .sheet Console logs confirm the state HAS changed But the UI does not update to reflect the new state Switching to another file in Xcode and back to ContentView instantly fixes the issue The production build (same code) works perfectly fine Environment Xcode: 16F6 (17C52) iOS: 26.2 (testing on iPhone 13) macOS: 25.1.0 (Sequoia) SwiftUI Target: iOS 15.6+ Issue: Present in both Xcode Canvas and on-device debugging Production: Same code works correctly in App Store build (version 1.3.2) Code Structure Parent View (ContentView.swift) struct ContentView: View { @State private var selectedSound: SoundTheme = .none @State private var showSoundSheet = false var body: some View { VStack { // Display button shows current selection SettingButton( title: "Background Sound", value: getLocalizedSoundName(selectedSound) // ← Not updating ) { showSoundSheet = true } } .sheet(isPresented: $showSoundSheet) { soundSelectionView } } private var soundSelectionView: some View { ForEach(SoundTheme.allCases) { sound in Button { selectedSound = sound // ← State DOES change (confirmed in console) // Audio starts playing correctly audioManager.startAmbientSound(sound) } label: { Text(sound.name) } } } private func getLocalizedSoundName(_ sound: SoundTheme) -> String { // Returns localized name return sound.localizedName }} What I've Tried Attempt 1: Adding .id() modifier SettingButton(...) .id(selectedSound) // Force re-render when state changes Result: No effect Attempt 2: Moving state modification outside withAnimation // Before (had animation wrapper):withAnimation { selectedSound = sound}// After (removed animation):selectedSound = sound Result: No effect Attempt 3: Adding debug print() statements selectedSound = soundprint("State changed: (selectedSound)") // ← Adding this line FIXES the issue! Result: Mysteriously fixes the issue! But removing print() breaks it again. This suggests a timing/synchronization issue in Xcode's preview system. Observations What works: ✅ Console logs confirm state changes correctly ✅ Switching files in Xcode triggers view reconstruction → everything works ✅ Production build from App Store works perfectly ✅ Adding print() statements "fixes" it (likely changes execution timing) What doesn't work: ❌ Initial file load in Xcode ❌ Hot reload / incremental updates ❌ Both Canvas preview and on-device debugging Workaround that works: Click another file in Xcode Click back to ContentView.swift Everything works normally Key Question Is this a known issue with Xcode 16's SwiftUI preview/hot reload system? The fact that: Same exact code works in production Adding print() "fixes" it File switching triggers reconstruction that fixes it ...all suggest this is an Xcode tooling issue, not a code bug. However, it makes development extremely difficult as I can't reliably test changes without constantly switching files or killing the app. What I'm Looking For Confirmation: Is this a known Xcode 16 issue? Workaround: Any better solution than constantly switching files? Root cause: What's causing this state update timing issue? Any insights would be greatly appreciated!
Topic: UI Frameworks SubTopic: SwiftUI
6
0
356
Dec ’25
Liquid Glass TabBar animations causes Hangs, bug with UIKitCore?
With iOS 26.1 we started seeing a bug that only appears on iPhone Air. This bug is visible with simulators too. I have tried so many different ways to fix the issue, but Instruments Profiler is pointing at UIKitCore. We load a tab bar, when the user attempts to switch a tab, the app hangs and never recovers. It happens right as the animation of the Glass bubble is in progress. I have tried a UIKit Tab bar, a SwiftUI Tab bar. I tore out AppDelegate and did a direct @main SwiftUI entry for my application. This issue appears with every tab bar instance I try. I attempted to disable LiquidGlass by utilizing this flag UIDesignRequiresCompatibility in my plist, but the flag seems to be ignored by the system. I am not sure what else to try. I have a trace file if that is helpful. What else can I upload? Here is what the code looks like. struct ContentView: View { @State private var selectedTab = 2 var body: some View { TabView(selection: $selectedTab) { Text("Profile") .tabItem { Label("Me", systemImage: "person") } .tag(0) Text("Training") .tabItem { Label("Training", systemImage: "calendar") } .tag(1) Text("Home") .tabItem { Label("Home", systemImage: "house") } .tag(2) Text("Goals") .tabItem { Label("Goals", systemImage: "target") } .tag(3) Text("Coach") .tabItem { Label("Coach", systemImage: "person.2") } .tag(4) } } } #Preview { ContentView() } and AppView entry point import SwiftUI @main struct RunCoachApp: App { var body: some Scene { WindowGroup { ContentView() } } }
6
1
493
Dec ’25
My app doesn't respond on iPhone Air iOS 26.1.
My app doesn't respond on iPhone Air iOS 26.1. After startup, my app shows the main view with a tab bar controller containing 4 navigation controllers. However, when a second-level view controller is pushed onto any navigation controller, the UI freezes and becomes unresponsive. The iPhone simulator running iOS 26.1 exhibits the same problem. The debug profile shows CPU usage at 100%. However, other devices and simulators do not have this problem.
6
3
467
Dec ’25
preferredTransition not working when using setViewControllers(_:animated:)
I’m using the new preferredTransition = .zoom(...) API introduced in iOS 18. Here’s a simplified version of what I do on app startup: let listVC = CollectionViewController(collectionViewLayout: layout) let detailVC = DetailViewController() detailVC.preferredTransition = .zoom(sourceViewProvider: { context in let indexPath = IndexPath(row: 0, section: 0) let cell = listVC.collectionView.cellForItem(at: indexPath) return cell }) let nav = UINavigationController() nav.setViewControllers([listVC, detailVC], animated: false) window?.rootViewController = nav window?.makeKeyAndVisible() This is meant to restore the UI state from a previous session — the app should launch directly into the DetailViewController. The Problem When I launch the app with setViewControllers([listVC, detailVC], animated: false), the transition from listVC to detailVC appears correctly (i.e., no animation, as intended), but the drag-to-dismiss gesture does not work. The back button appears, and tapping it correctly triggers the zoom-out transition back to the cell, so the preferredTransition = .zoom(...) itself is properly configured. Interestingly, if I delay the push with a DispatchQueue.main.async and instead do: nav.setViewControllers([listVC], animated: false) DispatchQueue.main.async { nav.pushViewController(detailVC, animated: true) } …then everything works perfectly — including the interactive swipe-to-dismiss gesture — but that introduces an unwanted visual artifact: the user briefly sees the listVC, and then it pushes to detailVC, which I’m trying to avoid. My Question Is there a way to enable the swipe-to-dismiss gesture when using setViewControllers([listVC, detailVC], animated: false) It can be very confusing for users if swipe-to-dismiss only works in certain cases inconsistently. Thanks
6
0
318
Sep ’25
iOS 18.4 (?) FamilyActivityPicker regression: presenting SFSafariViewController on top bugs
If I present "SFSafariViewController" when a "FamilyActivityPicker" is visible, it will automatically dismiss the "SFSafariViewController" and crash the "FamilyActivityPicker." I'm assuming the cause of the bug is that each is in a separate process (aside from the app), and there's some hacks to try to stop "FamilyActivityPicker" from crashing, and this is causing the new bug because "SFSafariViewController" is also in a separate process. (I'm not 100% if its just in 18.4 or iOS 18 overall...) (I'll try to file a feedback soon, but its 100% reproducible for me across multiple devices on iOS 18.4)
6
0
279
Apr ’25
Preview crashes when using ForEach with a Binding to an array and generics
The following repro case results in a previews crash on Xcode 26 beta 3 (report attached). FB18762054 import SwiftUI final class MyItem: Identifiable, Labelled { var label: String init(_ label: String) { self.label = label } } protocol Labelled { var label: String { get } } struct HelloView: View { let label: String var body: some View { Text(label) } } struct ListView<Element: Labelled & Identifiable>: View { @Binding var elements: [Element] var body: some View { List { ForEach($elements, id: \.id) { $element in HelloView(label: element.label) // crash // Replacing the above with a predefined view works correctly // Text(element.label) } } } } struct ForEachBindingRepro: View { @State var elements: [MyItem] = [ MyItem("hello"), MyItem("world"), ] var body: some View { ListView(elements: $elements) } } #Preview("ForEachBindingRepro") { ForEachBindingRepro() } foreachbindingrepro-2025-07-12-020628.ips
6
0
288
Jul ’25