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

Trigger save of a FileDocument in a DocumentGroup?
I have a DocumentGroup working with a FileDocument, and that's fine. However, when someone creates a new document I want them to have to immediately save it. This is the behavior on ipadOS and iOS from what I can understand (you select where before the file is created). There seems to be no way to do this on macOS? I basically want to have someone: create a new document enter some basic data hit "create" which saves the file then lets the user start editing it (1), (2), and (4) are done and fairly trivial. (3) seems impossible, though...? This really only needs to support macOS but any pointers would be appreciated.
0
0
241
Apr ’25
[SwiftUI] Gesture Conflict: simultaneousGesture Causes Incorrect Gesture Recognition in iOS 18
Subject: SwiftUI Gesture Conflict in iOS 18: Simultaneous Recognition of Drag and Tap Gestures Description: In SwiftUI on iOS 18 and above, we've identified an issue with gesture handling that affects user experience. When implementing .simultaneousGesture(DragGesture()), the system incorrectly recognizes and processes both drag and tap gestures concurrently, resulting in unintended behavior. Technical Details: Environment: SwiftUI, iOS 18+ Issue: Simultaneous recognition of horizontal drag gestures and vertical scroll/tap gestures Current Behavior: Both vertical and horizontal scrolling occur simultaneously when using .simultaneousGesture(DragGesture()) Expected Behavior: Gestures should be properly disambiguated to prevent concurrent scrolling in multiple directions Impact: This behavior significantly impacts user experience, particularly in custom carousel implementations and other UI components that rely on precise gesture handling. The simultaneous recognition of both gestures creates a confusing and unpredictable interaction pattern. Steps to Reproduce: Create a SwiftUI view with horizontal scrolling (e.g., custom carousel) Implement .simultaneousGesture(DragGesture()) Add tap gesture recognition to child views Run on iOS 18 Attempt to scroll horizontally Observed Result: Both horizontal dragging and vertical scrolling/tapping are recognized and processed simultaneously, creating an inconsistent user experience. Expected Result: The system should properly disambiguate between horizontal drag gestures and vertical scroll/tap gestures, allowing only one type of gesture to be recognized at a time based on the user's intent. Please let me know if you need any additional information or reproduction steps.
0
0
120
Apr ’25
SensorKit Data Not Retrieving
I have received permission from Apple to access SensorKit data for my app. I have granted all necessary permissions, but no data is being retrieved. The didCompleteFetch method is being called, but I’m unsure where to find event data like Device Usage and Ambient Light. Additionally, the didFetchResult method is never called. Could anyone please assist me in resolving this issue? Any guidance or troubleshooting steps would be greatly appreciated. import SensorKit class ViewController: UIViewController, SRSensorReaderDelegate { let store = SRSensorReader(sensor: .deviceUsageReport) override func viewDidLoad() { super.viewDidLoad() requestSensorAuthorization() } func requestSensorAuthorization() { var sensors: Set<SRSensor> = [ .accelerometer, .deviceUsageReport, .messagesUsageReport, .visits, .keyboardMetrics, .phoneUsageReport, .ambientLightSensor ] if #available(iOS 16.4, *) { sensors.insert(.mediaEvents) } SRSensorReader.requestAuthorization(sensors: sensors) { error in if let error = error { print("Authorization failed: \(error.localizedDescription)") } else { self.store.startRecording() self.requestSensorData() print("Authorization granted for requested sensors.") } } } func requestSensorData() { let fromTime = SRAbsoluteTime.fromCFAbsoluteTime(_cf: Date().addingTimeInterval(-60 * 60).timeIntervalSinceReferenceDate) let toTime = SRAbsoluteTime.fromCFAbsoluteTime(_cf: Date().timeIntervalSinceReferenceDate) let request = SRFetchRequest() request.from = fromTime request.to = toTime request.device = SRDevice.current store.fetch(request) store.delegate = self } func sensorReader(_ reader: SRSensorReader, didCompleteFetch fetchRequest: SRFetchRequest) { print("Fetch request completed: \(fetchRequest.from) to \(fetchRequest.to)") Task { do { let samples = try await reader.fetch(fetchRequest) print("Samples count: \(samples)") } catch { print("Error Fetching Data: \(error.localizedDescription)") } } } func sensorReader(_ reader: SRSensorReader, fetching fetchRequest: SRFetchRequest, didFetchResult result: SRFetchResult<AnyObject>) -> Bool { print(result) return true } }
0
0
248
Mar ’25
Live Activity resets to initial state after 8+ hours in background
Hi Apple team and community, We’re encountering a strange issue with Live Activity that seems related to memory management or background lifecycle. ❓ Issue: Our app updates a Live Activity regularly (every 3 minutes) using .update(...). However, after the app remains in the background for around 8 hours, the Live Activity reverts to the initial state that was passed into .request(...). Even though the app continues sending updates in the background, the UI on the Lock Screen and Dynamic Island resets to the original state.
0
0
69
Apr ’25
How to truncate text from head with multi line?
I want to truncate text from head with max 2 lines. I try the following code import SwiftUI struct ContentView: View { @State var content: String = "Hello world! wef wefwwfe wfewe weweffwefwwfwe wfwe" var body: some View { VStack { Text(content) .lineLimit(nil) .truncationMode(.head) .frame(height: 50) Button { content += content } label: { Text("Double") } .buttonStyle(.borderedProminent) } .frame(width: 200, height: 1000) .padding() } } #Preview { ContentView() } It show result like this, this is not what I want.
0
0
246
Mar ’25
SwiftUI Tabview - how to "kill" the views we do not use
I have the MainView as the active view if the user is logged in(authenticated). the memory allocations when we run profile is pretty good. We have graphql fetching, we have token handling eg: This is All heap: 1 All Heap & Anonymous VM 13,90 MiB 65408 308557 99,10 MiB 373965 Ratio: %0.14, %0.86 After what i have checked this is pretty good for initialise and using multiple repositories eg. But when we change tabs: 1 All Heap & Anonymous VM 24,60 MiB 124651 543832 156,17 MiB 668483 Ratio: %0.07, %0.40 And that is not pretty good. So i guess we need to "kill" it or something. How? I have tried some techniques in a forum this was a recommended way: public struct LazyView<Content: View>: View { private let build: () -> Content @State private var isVisible = false public init(_ build: @escaping () -> Content) { self.build = build } public var body: some View { build() Group { if isVisible { build() } else { Color.clear } } .onAppear { isVisible = true } .onDisappear { isVisible = false } } } But this did not help at all. So under here is the one i use now. So pleace guide me for making this work. import DIKit import CoreKit import PresentationKit import DomainKit public struct MainView: View { @Injected((any MainViewModelProtocol).self) private var viewModel private var selectedTabBinding: Binding<MainTab> { Binding( get: { viewModel.selectedTab }, set: { viewModel.selectTab($0) } ) } public init() { // No additional setup needed } public var body: some View { NavigationStack(path: Binding( get: { viewModel.navigationPath }, set: { _ in } )) { TabView(selection: selectedTabBinding) { LazyView { FeedTabView() } .tabItem { Label("Feed", systemImage: "house") } .tag(MainTab.feed) LazyView { ChatTabView() } .tabItem { Label("Chat", systemImage: "message") } .tag(MainTab.chat) LazyView { JobsTabView() } .tabItem { Label("Jobs", systemImage: "briefcase") } .tag(MainTab.jobs) LazyView { ProfileTabView() } .tabItem { Label("Profile", systemImage: "person") } .tag(MainTab.profile) } .accentColor(.primary) .navigationDestination(for: MainNavigationDestination.self) { destination in switch destination { case .profile(let userId): Text("Profile for \(userId)") case .settings: Text("Settings") case .jobDetails(let id): Text("Job details for \(id)") case .chatThread(let id): Text("Chat thread \(id)") } } } } } import SwiftUI public struct LazyView<Content: View>: View { private let build: () -> Content public init(_ build: @escaping () -> Content) { self.build = build } public var body: some View { build() } }
0
0
215
Mar ’25
`UIGraphicsImageRenderer` + `drawHierarchy` gives very flat colors
My setup: a UILabel with text in it and then let aBugRenderer = UIGraphicsImageRenderer(size: aBugLabel.bounds.size) let aBugImage = aBugRenderer.image { context in aBugLabel.drawHierarchy(in: aBugLabel.bounds, afterScreenUpdates: true) } The layout and everything is correct, the image is correct, but I used my colors in the displayP3 color space to configure the source UILabel.textColor And unfortunately, the resulted image ends up being sRGB IEC61966-2.1 color space and the color appears way bleaker than when it's drawn natively. Question: how can I set up the renderer so that it draws the same color.
0
0
168
Jun ’25
detecting modifier keys using UITextFieldDelegate protocol
I have a UITextField in my application, and I want to detect all the keys uniquely to perform all relevant task. However, there is some problem in cleanly identifying some of the keys. I m not able to identify the backspace key press in the textField(_:shouldChangeCharactersIn:replacementString:) method. Also I don't know how to detect the Caps Lock key. I am intending to so this because I want to perform some custom handling for some keys. Can someone help me with what is the way of detecting it under the recommendation from apple. Thanks in advance. Note: checking for replacementString parameter in shouldChangeCharactersIn method for empty does not help for backspace detection as it overlaps with other cases.
Topic: UI Frameworks SubTopic: UIKit Tags:
0
0
152
Mar ’25
Button Behavior between fullScreenCover and sheet
The behavior of the Button in ScrollView differs depending on how the View is displayed modally. When the View is displayed as a .fullScreenCover, if the button is touched and scrolled without releasing the finger, the touch event is canceled and the action of the Button is not called. On the other hand, if the View is displayed as a .sheet, the touch event is not canceled even if the view is scrolled without lifting the finger, and the action is called when the finger is released. In order to prevent accidental interaction, I feel that the behavior of .fullScreenCover is better, as it cancels the event immediately when scrolling. Can I change the behavior of .sheet? Demo movie is here: https://x.com/kenmaz/status/1896498312737611891 Sample code import SwiftUI @main struct SampleApp: App { var body: some Scene { WindowGroup { ContentView() } } } struct ContentView: View { @State private var showSheet = false @State private var showFullScreen = false var body: some View { VStack(spacing: 16) { Button("Sheet") { showSheet.toggle() } Button("Full screen") { showFullScreen.toggle() } } .sheet(isPresented: $showSheet) { SecondView() } .fullScreenCover(isPresented: $showFullScreen) { SecondView() } .font(.title) } } struct SecondView: View { @Environment(\.dismiss) var dismiss var body: some View { ScrollView { Button("Dismiss") { dismiss() } .buttonStyle(MyButtonStyle()) .padding(.top, 128) .font(.title) } } } private struct MyButtonStyle: ButtonStyle { func makeBody(configuration: Self.Configuration) -> some View { configuration .label .foregroundStyle(.red) .background(configuration.isPressed ? .gray : .clear) } }
Topic: UI Frameworks SubTopic: SwiftUI
0
0
190
Mar ’25
@Observable with generic typed throw breaks SwiftCompile
@Observable seems not to work well with generic typed throw. The following code using @Observable with non-generic typed throw builds good: @Observable class ThrowsLoadingViewModel<R, E: Error> { private(set) var isLoading = true private(set) var error: E? = nil private(set) var data: R? = nil private var task: () throws(Error) -> R init(task: @escaping () throws(E) -> R) { self.task = task } func load() { do throws(Error) { self.data = try task() } catch { // self.error = error } self.isLoading = false } } But if I change Line 7 and 14 to generic, it'll breaks the build with a "Command SwiftCompile failed with a nonzero exit code" message : @Observable class ThrowsLoadingViewModel<R, E: Error> { private(set) var isLoading = true private(set) var error: E? = nil private(set) var data: R? = nil private var task: () throws(E) -> R init(task: @escaping () throws(E) -> R) { self.task = task } func load() { do throws(E) { self.data = try task() } catch { // self.error = error } self.isLoading = false } } A the same time, if I remove @Observable, the generic typed throw works again: class ThrowsLoadingViewModel<R, E: Error> { private(set) var isLoading = true private(set) var error: E? = nil private(set) var data: R? = nil private var task: () throws(E) -> R init(task: @escaping () throws(E) -> R) { self.task = task } func load() { do throws(E) { self.data = try task() } catch { // self.error = error } self.isLoading = false } } Currently the possible solution seems to fall back to use ObservableObject...
0
0
91
Jun ’25
Replaykit stop screen record failed, recording status is false
I want to record screen ,and than when I call the method stopCaptureWithHandler:(nullable void (^)(NSError *_Nullable error))handler to stop recording and saving file. before call it,I check the value record of RPScreenRecorder sharedRecorder ,the value is false , It's weird! The screen is currently being recorded ! I wonder if the value of [RPScreenRecorder sharedRecorder].record will affect the method stopCaptureWithHandler: -(void)startCaptureScreen { [[RPScreenRecorder sharedRecorder] startCaptureWithHandler:^(CMSampleBufferRef _Nonnull sampleBuffer, RPSampleBufferType bufferType, NSError * _Nullable error) { //code } completionHandler:^(NSError * _Nullable error) { //code }]; } - (void)stopRecordingHandler { if([[RPScreenRecorder sharedRecorder] isRecording]){ // deal error .sometime isRecording is false }else { [[RPScreenRecorder sharedRecorder] stopCaptureWithHandler:^(NSError * _Nullable error) { }]; } } here are my code.
0
0
104
Apr ’25
Activate hoverEffect on separate entity attachment view
Hi, I'm working on RealityView and I have two entities in RCP. In order to set views for both entities, I have to create two separate attachments for each entity. What I want to achieve is that when I hover (by eye) on one entity's attachment, it would trigger the hover effect of the other entity's attachment. I try to use the hoverEffectGroup, but it would only activate the hover effect in a subview, instead a complete separate view. I refer to the following WWDC instruction for the hover effect. https://developer.apple.com/videos/play/wwdc2024/10152/
0
0
77
Apr ’25
SwiftUI TextEditor undo button
I'm using SwiftUI's TextEditor. I'd like to include an undo button in my UI that operates on the TextEditor. I don't see a way to hook this up. You can get the UndoManager from the environment, but this is not the undo manager the TextEditor is using. I know that UITextView uses an undocumented UndoManager (_UITextUndoManager) and I've accessed that before when using a UIViewRepresentable wrapper around UITextView. I'd like to achieve the same with TextEditor.
Topic: UI Frameworks SubTopic: SwiftUI
0
0
90
Jun ’25
PhoneSceneDelegate white screen
I am currently implementing multiple scenes in my React Native / Swift application (one scene for the phone and one scene for CarPlay). I am facing an issue where one scene renders completely white (on the iPhone) but I can see in the console that the code is running (for example if I add a console.log to the App.tsx I can see that console log happen in XCode). There are no errors when building the app in XCode, and testing with the simulator CarPlay appears to render the correct output, but there is no component being rendered on the simulated phone screen (just white). AppDelegate.swift import CarPlay import React import React_RCTAppDelegate import ReactAppDependencyProvider import UIKit @main class AppDelegate: RCTAppDelegate { var rootView: UIView?; static var shared: AppDelegate { return UIApplication.shared.delegate as! AppDelegate } override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { self.moduleName = "appName" self.dependencyProvider = RCTAppDependencyProvider() self.initialProps = [:] self.rootView = self.createRootView( with: RCTBridge( delegate: self, launchOptions: launchOptions ), moduleName: self.moduleName!, initProps: self.initialProps! ); return super.application(application, didFinishLaunchingWithOptions: launchOptions) } override func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { if (connectingSceneSession.role == UISceneSession.Role.carTemplateApplication) { let scene = UISceneConfiguration(name: "CarPlay", sessionRole: connectingSceneSession.role) scene.delegateClass = CarSceneDelegate.self return scene } let scene = UISceneConfiguration(name: "Phone", sessionRole: connectingSceneSession.role) scene.delegateClass = PhoneSceneDelegate.self return scene } override func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {} override func sourceURL(for bridge: RCTBridge) -> URL? { self.bundleURL() } override func bundleURL() -> URL? { #if DEBUG RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index") #else Bundle.main.url(forResource: "main", withExtension: "jsbundle") #endif } } PhoneSceneDelegate.swift import Foundation import UIKit import SwiftUI class PhoneSceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow?; func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { if session.role != .windowApplication { return } guard let appDelegate = (UIApplication.shared.delegate as? AppDelegate) else { return } guard let windowScene = (scene as? UIWindowScene) else { return } let rootViewController = UIViewController() rootViewController.view = appDelegate.rootView; let window = UIWindow(windowScene: windowScene) window.rootViewController = rootViewController self.window = window window.makeKeyAndVisible() } } App.tsx import React, {useEffect, useState} from 'react'; import type {PropsWithChildren} from 'react'; import {CarPlay, ListTemplate} from 'react-native-carplay'; import { ScrollView, StatusBar, StyleSheet, Text, useColorScheme, View, } from 'react-native'; import { Colors, DebugInstructions, Header, LearnMoreLinks, ReloadInstructions, } from 'react-native/Libraries/NewAppScreen'; type SectionProps = PropsWithChildren<{ title: string; }>; function Section({children, title}: SectionProps): React.JSX.Element { const isDarkMode = useColorScheme() === 'dark'; return ( <View style={styles.sectionContainer}> <Text style={[ styles.sectionTitle, { color: isDarkMode ? Colors.white : Colors.black, }, ]}> {title} </Text> <Text style={[ styles.sectionDescription, { color: isDarkMode ? Colors.light : Colors.dark, }, ]}> {children} </Text> </View> ); } function App(): any { // React.JSX.Element const isDarkMode = useColorScheme() === 'dark'; const backgroundStyle = { backgroundColor: isDarkMode ? Colors.darker : Colors.lighter, }; const [carPlayConnected, setCarPlayConnected] = useState(CarPlay.connected); useEffect(() => { function onConnect() { setCarPlayConnected(true); CarPlay.setRootTemplate(new ListTemplate(/** This renders fine on the CarPlay side */)); } function onDisconnect() { setCarPlayConnected(false); } CarPlay.registerOnConnect(onConnect); CarPlay.registerOnDisconnect(onDisconnect); return () => { CarPlay.unregisterOnConnect(onConnect); CarPlay.unregisterOnDisconnect(onDisconnect); }; }); if (carPlayConnected) { console.log('car play connected'); } else { console.log('car play not connected'); } const safePadding = '5%'; // This doesn't render on the phone? return ( <View style={backgroundStyle}> <StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} backgroundColor={backgroundStyle.backgroundColor} /> <ScrollView style={backgroundStyle}> <View style={{paddingRight: safePadding}}> <Header/> </View> <View style={{ backgroundColor: isDarkMode ? Colors.black : Colors.white, paddingHorizontal: safePadding, paddingBottom: safePadding, }}> <Section title="Step One"> Edit <Text style={styles.highlight}>App.tsx</Text> to change this screen and then come back to see your edits. </Section> <Section title="See Your Changes"> <ReloadInstructions /> </Section> <Section title="Debug"> <DebugInstructions /> </Section> <Section title="Learn More"> Read the docs to discover what to do next: </Section> <LearnMoreLinks /> </View> </ScrollView> </View> ); } const styles = StyleSheet.create({ sectionContainer: { marginTop: 32, paddingHorizontal: 24, }, sectionTitle: { fontSize: 24, fontWeight: '600', }, sectionDescription: { marginTop: 8, fontSize: 18, fontWeight: '400', }, highlight: { fontWeight: '700', }, }); export default App; I have been attempting to get this working now for some 20+ hours with no luck with searching for answers elsewhere. I am very new to building apps with React Native and Swift so could do with some support.
0
0
361
Mar ’25
Custom, Markdown autocapitalizationType.
Hi, I've got an app that displays markdown in UITextView / NSTextView. I would like it to behave like Notes app does, that is if user types the line start modifier, e.g: "# " or "> " I would like the keyboard to show a capitalized letters. I've tried looking into overriding insertText - and it breaks the predictive text (can not insert white space). I've tried implementing UITextInputTokenizer but no luck either. Like I said, I see the Notes app does it perfectly, so maybe I'm missing something obvious or there is a way to do it without interrupting the auto-correction and predictive text. Ideally same thing can be applied to the NSTextView as the app support both platforms.
Topic: UI Frameworks SubTopic: UIKit Tags:
0
0
163
May ’25
How to determine which ui control is found first in the view hierarchy, when I assign the same keyboardShortcut () to 2 buttons?
import SwiftUI struct ContentView: View { var body: some View { VStack { Button ("Button 1") { print ("Button 1"); } .keyboardShortcut("k", modifiers: .command) Button ("Button 2") { print ("Button 2"); } .keyboardShortcut("k", modifiers: .command) } } } I the above snippet, I have assigned the same keyboard shortcut (cmd +k) to 2 different buttons. According to the docs, if multiple controls are associated with the same shortcut, the first one found is used. How do I figure out if Button 1 would be found first during the traversal or Button 2 ? Is it based on the order of declaration? Is it always the case that Button 1 would be found first since it was declared before Button 2 ?
0
0
116
Mar ’25
Regarding ARKit camera feed zoom and macro support for closer object
I am currently developing an AR experience using ARKit with SceneKit and am looking to implement functionality that enables: Zooming into the AR camera feed, ideally leveraging the ultra-wide or telephoto lenses available on supported devices. Macro-style focus capabilities, allowing users to view and interact with virtual content closely aligned with small or nearby real-world objects (within a few centimeters). My objective is to ensure that ARKit continues to render the scene accurately while enabling a zoomed-in view or macro-level focus for better detail visibility and alignment. Could you please advise on: Whether ARKit currently supports camera zoom or allows access to macro or ultra-wide cameras within an ARSession. Limitations or considerations when using multi-camera setups in conjunction with ARKit. Any guidance or references to documentation or sample code would be greatly appreciated. Best regards, Ayush
0
0
132
May ’25
A wrinkle converting a UIKit Document-based app to SwiftUI Document Group
The app I'm converting includes two unique document types. UI-wise they have key similarities (eg contents are password protected) But serialization/model - wise. they are different documents. I have not been able to find any documentation on options for implementing this (eg use a (abstract?) base class derived from FileDocument, with two concrete sub classes? maybe just a single subclass of FileDocument that contains model details for both file types?) Stepping back from implementation options, am I crazy for attempting to use DocumentGroup to create a single app that would need to be able to open/modify/save multiple unique document types? any/all guidance much appreciated.
Topic: UI Frameworks SubTopic: SwiftUI
0
0
70
May ’25
Use Custom UIApplication Subclass with SwiftUI
I have a SwiftUI app which needs the Ivanti AppConnect SDK. The docs only show how to integrate it into a Swift/UIKit app. But I need it to work with SwiftUI. I probably could make a UIKit base app and then load my existing SwiftUI views and code through a SwiftUI component host or something. But I'd like to avoid that if possible. Here is where I'm stuck: The AppConnect framework loads through a custom UIApplication subclass in the main.swift file: import Foundation import AppConnect UIApplicationMain( CommandLine.argc, CommandLine.unsafeArgv, ACUIApplicationClassName, NSStringFromClass(AppDelegate.self) ) The startup works as expected, and the expected function is called in the AppDelegate class: func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {...} However, the SwiftUI view is not loaded and the scree stays blank. I implemented a SceneDelegate.swift class which doesn't seem to be called. Also, the following function in the AppDelegate doesn't get called either: func application( _ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {...} So how do I bootstrap SwiftUI with a custom UIApplication class? can that be done with the @main macro somehow? I'm still pretty new to Swift and iOS development. Any help is appreciated
Topic: UI Frameworks SubTopic: SwiftUI Tags:
0
0
71
May ’25