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

Created

A Summary of the WWDC25 Group Lab - UI Frameworks
At WWDC25 we launched a new type of Lab event for the developer community - Group Labs. A Group Lab is a panel Q&A designed for a large audience of developers. Group Labs are a unique opportunity for the community to submit questions directly to a panel of Apple engineers and designers. Here are the highlights from the WWDC25 Group Lab for UI Frameworks. How would you recommend developers start adopting the new design? Start by focusing on the foundational structural elements of your application, working from the "top down" or "bottom up" based on your application's hierarchy. These structural changes, like edge-to-edge content and updated navigation and controls, often require corresponding code modifications. As a first step, recompile your application with the new SDK to see what updates are automatically applied, especially if you've been using standard controls. Then, carefully analyze where the new design elements can be applied to your UI, paying particular attention to custom controls or UI that could benefit from a refresh. Address the large structural items first then focus on smaller details is recommended. Will we need to migrate our UI code to Swift and SwiftUI to adopt the new design? No, you will not need to migrate your UI code to Swift and SwiftUI to adopt the new design. The UI frameworks fully support the new design, allowing you to migrate your app with as little effort as possible, especially if you've been using standard controls. The goal is to make it easy to adopt the new design, regardless of your current UI framework, to achieve a cohesive look across the operating system. What was the reason for choosing Liquid Glass over frosted glass, as used in visionOS? The choice of Liquid Glass was driven by the desire to bring content to life. The see-through nature of Liquid Glass enhances this effect. The appearance of Liquid Glass adapts based on its size; larger glass elements look more frosted, which aligns with the design of visionOS, where everything feels larger and benefits from the frosted look. What are best practices for apps that use customized navigation bars? The new design emphasizes behavior and transitions as much as static appearance. Consider whether you truly need a custom navigation bar, or if the system-provided controls can meet your needs. Explore new APIs for subtitles and custom views in navigation bars, designed to support common use cases. If you still require a custom solution, ensure you're respecting safe areas using APIs like SwiftUI's safeAreaInset. When working with Liquid Glass, group related buttons in shared containers to maintain design consistency. Finally, mark glass containers as interactive. For branding, instead of coloring the navigation bar directly, consider incorporating branding colors into the content area behind the Liquid Glass controls. This creates a dynamic effect where the color is visible through the glass and moves with the content as the user scrolls. I want to know why new UI Framework APIs aren’t backward compatible, specifically in SwiftUI? It leads to code with lots of if-else statements. Existing APIs have been updated to work with the new design where possible, ensuring that apps using those APIs will adopt the new design and function on both older and newer operating systems. However, new APIs often depend on deep integration across the framework and graphics stack, making backward compatibility impractical. When using these new APIs, it's important to consider how they fit within the context of the latest OS. The use of if-else statements allows you to maintain compatibility with older systems while taking full advantage of the new APIs and design features on newer systems. If you are using new APIs, it likely means you are implementing something very specific to the new design language. Using conditional code allows you to intentionally create different code paths for the new design versus older operating systems. Prefer to use if #available where appropriate to intentionally adopt new design elements. Are there any Liquid Glass materials in iOS or macOS that are only available as part of dedicated components? Or are all those materials available through new UIKit and AppKit views? Yes, some variations of the Liquid Glass material are exclusively available through dedicated components like sliders, segmented controls, and tab bars. However, the "regular" and "clear" glass materials should satisfy most application requirements. If you encounter situations where these options are insufficient, please file feedback. If I were to create an app today, how should I design it to make it future proof using Liquid Glass? The best approach to future-proof your app is to utilize standard system controls and design your UI to align with the standard system look and feel. Using the framework-provided declarative API generally leads to easier adoption of future design changes, as you're expressing intent rather than specifying pixel-perfect visuals. Pay close attention to the design sessions offered this year, which cover the design motivation behind the Liquid Glass material and best practices for its use. Is it possible to implement your own sidebar on macOS without NSSplitViewController, but still provide the Liquid Glass appearance? While technically possible to create a custom sidebar that approximates the Liquid Glass appearance without using NSSplitViewController, it is not recommended. The system implementation of the sidebar involves significant unseen complexity, including interlayering with scroll edge effects and fullscreen behaviors. NSSplitViewController provides the necessary level of abstraction for the framework to handle these details correctly. Regarding the SceneDelagate and scene based life-cycle, I would like to confirm that AppDelegate is not going away. Also if the above is a correct understanding, is there any advice as to what should, and should not, be moved to the SceneDelegate? UIApplicationDelegate is not going away and still serves a purpose for application-level interactions with the system and managing scenes at a higher level. Move code related to your app's scene or UI into the UISceneDelegate. Remember that adopting scenes doesn't necessarily mean supporting multiple scenes; an app can be scene-based but still support only one scene. Refer to the tech note Migrating to the UIKit scene-based life cycle and the Make your UIKit app more flexible WWDC25 session for more information.
Topic: UI Frameworks SubTopic: General
0
0
651
Jun ’25
Capture a List selection AND push a view
I've got a situation where I want the iPad to push an editing view onto the sidebar (like on iPhone) and also display a detail view (no content view). This is working great. However, I need to determine which item from a List in a NavigationSplitView has been selected and pass this to the detail view (the selection is out of scope). This works with the List selection parameter, but the item selected is ONLY selected and the child view in the NavigationLink does not get pushed, nor does the detail view get changed. I either need to figure out a way to capture the selection without the List Selection parameter (Tap Gesture?) or get the navigation to happen even when using the Selection parameter. I'd appreciate some ideas as I'm a newb just learning SwiftUI.
Topic: UI Frameworks SubTopic: SwiftUI
0
0
6
3h
Pickers in toolbar expand its width
With iOS 26 there has been a change in behavior with Pickers in the toolbar. The Picker looks expanded unlike other views such as a Button and Menu. See screenshots below. Is this the intended behavior or a bug? (I already submitted a feedback for this at FB19276474) What Picker looks like in the toolbar: What Button looks like in the toolbar:
0
0
29
9h
SwiftUI recursive list with children: programmatically expand nodes
I have a SwiftUI recursive list, created with the (children:) initializer, just like it's shown in the code example here: https://developer.apple.com/documentation/SwiftUI/List#Creating-hierarchical-lists I would like this tree view to be searchable (i.e a user enters a query into a text field and it searches the entire tree at all levels). Displaying a search result which is not at the top level would require its parents to be programmatically expanded. How to programmatically expand certain levels of such a list?
0
0
32
9h
Preventing crashes with ScrollViewProxy.scrollTo()
I have a search field and a List of search results. As the user types in the search field, the List is updated with new results. Crucially, with each update, I want to reset the List's scroll position back to the top. To achieve this, I'm using the following .onChange() modifier along with a ScrollViewReader: .onChange(of: searchQuery) { _, newQuery in Task { searchResults = await searchLibrary(for: newQuery) scrollViewProxy.scrollTo(0, anchor: .top) } } My List uses index-based IDs, so scrolling to 0 should always go to the first item. The above code works, but crashes if searchResults is empty because there is no item in the List with an ID of 0. (As a side note, it seems rather excessive for the scrollTo() method to trigger a full-on crash just because the ID is not found; I don't think this should be anything more than a warning, or the method should throw an error that can be caught). To work around this, I added an isEmpty check, so we only attempt the scroll if the array is not empty: .onChange(of: searchQuery) { _, newQuery in Task { searchResults = await searchLibrary(for: newQuery) if !searchResults.isEmpty { scrollViewProxy.scrollTo(0, anchor: .top) } } } However, even with this check, I was seeing rare crashes in production, consistent with a race condition. My guess is that when searchResults is updated, the view is not recreated immediately, so if scrollTo() is called too quickly, the List may not yet be seeing the latest update to the searchResults array. I figured that I could try to delay the calling of scrollTo() to give the view time to update: .onChange(of: searchQuery) { _, newQuery in Task { searchResults = await searchLibrary(for: newQuery) if !searchResults.isEmpty { DispatchQueue.main.async { scrollViewProxy.scrollTo(0, anchor: .top) } } } } However, even with this, I've just received a crash report pointing to the same issue (the first in about four months). I'm not able to reproduce the bug myself – so it definitely seems like a rare race condition, probably relating to the timing of view updates. I guess, I can insert another isEmpty check before calling scrollTo(), but I'm starting to wonder if it's even possible to guarantee that the item will be in the List when scrollTo() performs its action, and because this is so hard to reproduce, I can't really test any ideas. Does anyone have any idea how (and at what point) the ScrollViewReader reads the view's current state? What's the right way to approach debugging a problem like this? Moreover, does anyone have any better suggestions about how to handle resetting the List position? The reason I want to do this is because, if the user types, scrolls a bit, and then types some more, the new results appear above the fold where the user can't see them, leading to a confusing experience. I thought about switching to the newer .scrollPosition() modifier, but that's only iOS 18+ and only for ScrollViews, not Lists. Cheers!
Topic: UI Frameworks SubTopic: SwiftUI
0
0
18
1d
SwiftData @Query causes UI Hierarchy crash
Simple code like struct ContentView: View { @Query var items: [Item] var body: some View { VStack { Image(systemName: "globe") .imageScale(.large) .foregroundStyle(.tint) Text("Hello, world!") } .padding() } } causes UI Hierarchy crash, on Simulators, iPhone and Mac I found no solution but use @State with fetch descriptor.
0
0
23
2d
tabBarMinimizeBehavior behavior in iOS 26
I'm trying to revamp the player into a floating style like Apple music. I use tabViewBottomAccessory with tabBarMinimizeBehavior. At the time, I noticed an issue that tabViewBottomAccessory would not automatically collapse when the scroll area was small (but still exceeded the screen height). tabViewBottomAccessory can only be automatically collapsed when the scroll area is large enough. Below is the simplest demo. I'm not sure if it's intentional or if it's a bug. Besides, I wonder if we can control it programmatically(expanded/inline)? struct ContentView: View { var body: some View { TabView { Tab("Numbers", systemImage: "number.circle") { List { // 200 works well, but 20 not ForEach(0..<200) { index in Text("\(index)") } } } } .tabBarMinimizeBehavior(.onScrollDown) .tabViewBottomAccessory { HStack { Text("SwiftUI Demo App") } } } }
1
0
99
2d
How to improve my SwiftUI tvOS app flow?
Hello, I'm thinking about how to improve my main tvOS app flow, naively I want to do something like this: import Combine import SwiftUI enum AppState { case login, onboarding, main } class AppStateManager { let appStatePublisher = PassthroughSubject<AppState, Never>() func updateState(_ appState: AppState) } struct tvOSApp: App { private var appState: AppState = .login private let appStateManager = AppStateManager() var body: some Scene { WindowGroup { ZStack { switch appState { case .login: LoginView() case .onboarding: OnboardingView() case .main: MainView() } } .onReceive(appStateManager.appStatePublisher) { self.appState = $0 } } } } So basically, MainView, OnboardingView and LoginView would be the main navigation views of my app, and the appStateManager would be a dependency passed to each of these views and allowing me to update the currently displayed view in the app. (of course I could use an Environment object instead for a 100% SwiftUI solution). I was wondering, however, if there is a better way to do this, instead of switching in a ZStack, maybe with WindowGroup/Window/Scenes? Thank you for your help!
0
0
35
2d
How to prevent window scene restoration
We have an iOS app running on macOS (not Mac Catalyst). The preferences are in a dedicated UIWindowScene. We don't want this scene to be restored, so when you start the app the preferences shouldn't be visible. How can we prevent the UIWindowScene restoration? Alternatively, if we can't prevent it, how can we ensure the main window scene is in front of the preferences window scene on app start?
Topic: UI Frameworks SubTopic: UIKit Tags:
0
0
23
2d
How to disable highlight state on Link in LA widget
I am working on a Live Activity widget. In it, I want some of the elements to open different deeplink URLs. I have found that assigning multiple widgetURL doesn't work, only one of the URLs gets opened no matter where you tap. I also found that Buttons don't seem to do anything, tapping them actually just open my app as if I just tapped a naked Live Activity. I have found that really only Link elements work if I want to open different URLs upon tapping different elements. And Links are cool and fine, but I am seeing that on tap, my elements become tinted... As in, there is a highlighted state, and it makes the elements inside blue. I have tried to use button style API on a link, but it didn't work. How can I disable the highlighted state for a Link element in a live activity widget?
0
0
40
2d
iOS 26 WKWebView STScreenTimeConfigurationObserver KVO Crash
Fatal Exception: NSInternalInconsistencyException Cannot remove an observer <WKWebView 0x135137800> for the key path "configuration.enforcesChildRestrictions" from <STScreenTimeConfigurationObserver 0x13c6d7460>, most likely because the value for the key "configuration" has changed without an appropriate KVO notification being sent. Check the KVO-compliance of the STScreenTimeConfigurationObserver [class.] I noticed that on iOS 26, WKWebView registers STScreenTimeConfigurationObserver, Is this an iOS 26 system issue? What should I do?
Topic: UI Frameworks SubTopic: UIKit Tags:
0
0
19
2d
UIBarButtonItem and Liquid Glass
I am looking for a way to change the liquid glass background colors on UIBarButtonItems. Setting tintColor does what I want for a bar button item when it is both the default button and it is enabled. But it does not seem to do anything for disabled buttons or non-prominent buttons. Also, is there a way to apply such a change using a UINavigationBarAppearance or a UIBarButtonItemAppearance? If I cannot change this liquid glass color, I might need to disable liquid glass on these by setting hidesSharedBackground to true. Is there a way to do this globally within the app (without using UIDesignRequiresCompatibility), or with something like UINavigationBarAppearance or UIBarButtonItemAppearance? Thank you. John
Topic: UI Frameworks SubTopic: UIKit
2
0
129
3d
Share Sheet with UIActivityItemsConfiguration
I am trying to address an issue with my app’s share sheet where, when the user sends a URL to either Apple Reminders or OmniFocus, the receiving app does not get a title. So I am updating my share sheet code to use UIActivityItemsConfiguration. I have this code: let title = "Golden Hill Software" let url = URL(string: "https://www.goldenhillsoftware.com/")! let itemProvider = NSItemProvider() itemProvider.registerObject(ofClass: URL.self, visibility: .all) { (handler) in handler(url, nil) return nil } let config = UIActivityItemsConfiguration(itemProviders: [itemProvider]) config.metadataProvider = { (key) in if key == .title || key == .messageBody { return title } else { return nil } } let viewController = UIActivityViewController(activityItemsConfiguration: config) self.present(viewController, animated: true) This works with some share sheet extensions. But when I choose the Ivory share extension, Ivory creates a post with a URL that starts with bplist…. When I choose the Open in Chrome action extension, Chrome says “Chrome cannot handle this link”. Can someone help me understand what I am doing wrong here? (edited)
Topic: UI Frameworks SubTopic: UIKit
0
0
19
3d
Delete Confirmation Dialog Inside Toolbar IOS26
inline-code How do you achieve this effect in toolbar? Where is the documentation for this? How to make it appear top toolbar or bottom toolbar? Thank you! Here is what I have now... .toolbar { ToolbarItem(placement: .destructiveAction) { Button { showConfirm = true } label: { Image(systemName: "trash") .foregroundColor(.red) } } } .confirmationDialog( "Are you sure?", isPresented: $showConfirm, titleVisibility: .visible ) { Button("Delete Item", role: .destructive) { print("Deleted") } Button("Archive", role: .none) { print("Archived") } Button("Cancel", role: .cancel) { } } }
0
0
29
3d
How do I prevent screenshots using SwiftUI?
Hi Team, How do I prevent screenshots using SwiftUI. I was using this solution on UIKit: extension UIView { func makeSecure() { DispatchQueue.main.async { let protectedView = UIView() self.superview?.addSubview(protectedView) // constraints... let secureView = SecureView() self.superview?.addSubview(secureView) // constraints... secureView.addSecureSubview(self) // constraints... } } } class SecureView: UIView { private lazy var secureField: UIView = { var secureField: UIView = UIView() // ... if let secureContainer = SecureField().secureContainer { secureField = secureContainer } ... return secureField }() required init() { ... } } Is it posible to do the same thing using SwiftUI. Do we have an example? What would you recommend when we work with confidencial information in SwiftUI like bank account information? Thanks in advance!
0
0
106
3d
Zoom navigation transitions for tabViewBottomAccessory are not working in SwiftUI with ObservableObject or Observable
The zoom navigation transition with matchedTransitionSource in tabViewBottomAccessory does not work when a Published var in an ObservableObjector Observable gets changed. Here is an minimal reproducible example with ObservableObject: import SwiftUI import Combine private final class ViewModel: ObservableObject { @Published var isPresented = false } struct ContentView: View { @Namespace private var namespace @StateObject private var viewModel = ViewModel() // @State private var isPresented = false var body: some View { TabView { Button { viewModel.isPresented = true } label: { Text("Start") } .tabItem { Image(systemName: "house") Text("Home") } Text("Search") .tabItem { Image(systemName: "magnifyingglass") Text("Search") } Text("Profile") .tabItem { Image(systemName: "person") Text("Profile") } } .sheet(isPresented: $viewModel.isPresented) { Text("Sheet") .presentationDragIndicator(.visible) .navigationTransition(.zoom(sourceID: "tabViewBottomAccessoryTransition", in: namespace)) } .tabViewBottomAccessory { Button { viewModel.isPresented = true } label: { Text("BottomAccessory") } .matchedTransitionSource(id: "tabViewBottomAccessoryTransition", in: namespace) } } } However, when using only a State property everything works: import SwiftUI import Combine private final class ViewModel: ObservableObject { @Published var isPresented = false } struct ContentView: View { @Namespace private var namespace // @StateObject private var viewModel = ViewModel() @State private var isPresented = false var body: some View { TabView { Button { isPresented = true } label: { Text("Start") } .tabItem { Image(systemName: "house") Text("Home") } Text("Search") .tabItem { Image(systemName: "magnifyingglass") Text("Search") } Text("Profile") .tabItem { Image(systemName: "person") Text("Profile") } } .sheet(isPresented: $isPresented) { Text("Sheet") .presentationDragIndicator(.visible) .navigationTransition(.zoom(sourceID: "tabViewBottomAccessoryTransition", in: namespace)) } .tabViewBottomAccessory { Button { isPresented = true } label: { Text("BottomAccessory") } .matchedTransitionSource(id: "tabViewBottomAccessoryTransition", in: namespace) } } }
0
0
49
3d
@state update not reflecting on UI.
I’m facing an issue in our native iOS app that occurs specifically on iOS 26.1 (not observed on any lower versions). When I update a @State field value, the UI does not reflect the change as expected. The @State variable updates internally, but the view does not re-render. This behaviour started after upgrading to iOS 26.1. Works fine on iOS 26.0 and earlier versions. Has anyone else encountered this issue or found a workaround? Any insights or suggestions would be greatly appreciated.
5
0
180
3d
PHPickerViewController displays the photo picker with shrunken UI
I need to create a Mac application using Objective-C. The application has to use PHPickerViewController to provide user a familiar interface to pick photos. Here is the Objective-C code that used to present the photo picker. //ViewController.h #import <Cocoa/Cocoa.h> #import <PhotosUI/PhotosUI.h> @interface ViewController : NSViewController<PHPickerViewControllerDelegate> @property (nonatomic, weak) IBOutlet NSImageView *myImageView; @end // ViewController.m @implementation ViewController PHPickerViewController* pickerViewController = nil; - (void)pickPhotos { PHPickerConfiguration *config = [[PHPickerConfiguration alloc] init]; config.selectionLimit = 0; // Allow multiple selections config.filter = [PHPickerFilter imagesFilter]; // Filter for images pickerViewController = [[PHPickerViewController alloc] initWithConfiguration:config]; pickerViewController.preferredContentSize = NSMakeSize(800, 600); pickerViewController.delegate = self; // Set the delegate to handle selection [self presentViewControllerAsModalWindow:pickerViewController]; - (IBAction)clicked:(id)sender { NSLog(@"Button Clicked"); [self pickPhotos]; } - (void)picker:(PHPickerViewController *)picker didFinishPicking:(NSArray<PHPickerResult *> *)results { if (pickerViewController) { [picker dismissViewController:pickerViewController]; } } @end Can you please guide me to show the photo picker to a bigger size?
Topic: UI Frameworks SubTopic: AppKit
4
0
110
4d