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

How to determine the default duration of a long-press
Using gesture recognizers it is easy to implement a long-press gesture to open a menu, show a preview or something else on the iOS platform. And you can provide the duration the user must hold down the finger until the gesture recognizer fires. But I could not yet find out how to determine the default duration for a long-press gesture that is configured in the system settings within the "accessibility" settings under "Haptic Touch" (the available options are fast, standard and slow here). Is it possible to read out this setting, so my App can adapt to this system setting as well?
1
0
358
Jan ’25
iPadOS 18 App (on Apple Silicon) - Duplicate Tab Bar Appearing in Toolbar
With iPadOS 18, the UITabBar now defaults to the floating style. I successfully reverted the tab bar to its traditional style by overriding the UITabBarController's horizontalSizeClass property: self.tabBarController?.traitOverrides.horizontalSizeClass = .unspecified When I launch the app on my Mac using Apple Silicon, TWO tab bars appear: One appears at the bottom of the screen, like a traditional tab bar. The second tab bar is still embedded in the app toolbar in its floating style. Is this a bug? How do you ensure that overriding the horizontalSizeClass will remove/hide the floating tab bar when running an app on Apple Silicon? TIA! (Demonstrated on a test project)
0
0
484
Jan ’25
Single window keyboard shortcut
I made a macOS document-based app that has a second scene that's a Window. It's name appears in the single window list of the Windows menu, but has no assigned shortcut. I've tried the following to assign a shortcut to it, but it doesn't add a "⌘L" as I want: Window("Logs", id: "logs") { LogsView() } .keyboardShortcut("l") I can brute-force this using .commands to replace the menu item but that seems crude and unnecessary. Is it the only way?
2
0
478
Jan ’25
SwiftUI Canvas Text - scale to fill rectangle
How do I draw a single line of text in a SwiftUI Canvas, scaled to fill a given rectangle? Example: Canvas { context, size in let r = CGRect(origin: CGPointZero, size: size); // Whole canvas let t = Text("Hello World"); context.draw(t, in: r); } Outside of Canvas I'd add .minimumScaleFactor(0) .lineLimit(1), and I guess set a large default font size, and I'd get the result I want. But inside Canvas, .minimumScaleFactor and .lineLimit don't seem to be available; they return some View, not Text, which can't be used in context.draw. (Is there a trick to make that work?) I have written the following to do this, but I think there must be an easier way to achieve this! Suggestions? extension GraphicsContext { mutating func draw_text_in_rect(string: String, rect: CGRect) { let text = Text(string) .font(.system(size: 25)); // The font size used here does matter, because e.g. letter spacing // varies with the font size. let resolved = resolve(text); let text_size = resolved.measure(in: CGSize(width: CGFloat.infinity, height: CGFloat.infinity)); let text_aspect = text_size.width / text_size.height; let fit_size = CGSize(width: min(rect.size.width, rect.size.height*text_aspect), height: min(rect.size.height, rect.size.width/text_aspect)); let fit_rect = CGRect(x: rect.origin.x + (rect.size.width-fit_size.width)/2, y: rect.origin.y + (rect.size.height-fit_size.height)/2, width: fit_size.width, height: fit_size.height); let scale = fit_size.width / text_size.width; // For debug: // var p = Path(); // p.addRect(fit_rect); // stroke(p, with: GraphicsContext.Shading.color(.red), lineWidth: 1); translateBy(x: fit_rect.minX, y: fit_rect.minY); scaleBy(x:scale, y:scale); draw(resolved, at: CGPointZero, anchor: UnitPoint.topLeading); transform = CGAffineTransformIdentity; } };
0
0
368
Jan ’25
INUIHostedViewControlling ViewController's Life Cycle Events not being Called
I am implementing a new Intents UI Extension and am noticing that the viewWillDisappear, viewDidDisappear, and deinit methods are not being called on my UIViewController that implements INUIHostedViewControlling, when pressing the "Done" button and dismissing the UIViewController. This causes the memory for the UI Extension to slowly increase each time I re-run the UI Extension until it reaches the 120MB limit and crashes. Any ideas as to what's going on here and how to solve this issue?
2
0
417
Jan ’25
Switching apps in 15.2 causes strange error
My app is the client in a client-server document management system. It supports scanning, indexing, and creation of various types documents including PDF, TIFF, various image types, and text. Upon installation of macOS 15.2, I am getting a strange NSInternalInconsistencyException error so long as the following are true: I have created or opened a PDF (or other type) document I click on the desktop/Finder or other app Normally, I would expect this action to put my App in the background, but before that happens, the error is thrown. I am not connected any server at the time. My app is built catch unhandled exceptions and this is what is displayed: At the time the error is thrown, [NSApp mainWindow] appears to be set to nil, but I have no idea if this occurred as result of becoming the background app or because of something I am doing wrong. I never set mainWindow anywhere in my app. I've tried to set a Waitchpoint or various waist try and catch when mainWindow changes, but have come up empty. Note the error is thrown if I hit a breakpoint when debugging in Xcode (because it switches to Xcode). This errors never occurred with previous releases and does not occur when the app is run under 15.1. The app is written in ObjectiveC. I've looked at various app-level flags and info.plist properties and nothing I've seen jumps out at me. I strongly suspect this error is a result of some system-level app attempting to create a UserActivity file (perhaps encrypted) that it can store in the cloud (a feature we would rather not use yet). It could also be trying to do an autosave on my open document-based windows - our NIB files that apply to our documents are marked as Restorable and they worked in prior system releases. Turning the Restorable flag off has no effect on the error. Any clue what I might be missing here? I've spent an embarrassing number of days trying to understand why this is happening.
Topic: UI Frameworks SubTopic: General
1
0
281
Jan ’25
Typographic question for space character
In this UIKit app, I have to display numbers (from 1 to 100), in a label., on several lines, with 8 numbers on each line. Order is computed by the app for a specific purpose. The numbers are separated by space. Label font is Helvetica Neue 15.0. I want to get them aligned vertically. So, I have a padding so that they are all the same length of 4. Problem: the space have smaller width (half in fact) than digits, so alignment is disrupted: Of course, I can use fixed width fonts (like Menlo), but I've not found one that fits (the zero is barred, which is not looking great in the app). I have tried using class func monospacedDigitSystemFont( ofSize fontSize: CGFloat, weight: UIFont.Weight ) -> UIFont and apply to label.text. To no avail as it modifies only digits, not space char. I have found a workaround, padding with 2 spaces instead of one, but is there another solution ? So I am looking for a space character that would have the same width as a digit. There existe thin space (https://en.wikipedia.org/wiki/Whitespace_character) but not larger space. Does it exist ?
5
0
675
Jan ’25
Unable to display SwiftUI View Previews in a Static Framework target
Hello, I am currently encountering an issue where SwiftUI View Previews cannot be displayed when the View is defined in a Static Framework target. This issue only occurs under specific conditions. Environment Xcode: 16.2 Scheme Structure: MainApp Test Target: TestHogeFeature Test Setting: Gather coverage (Code coverage collection) enabled(all) Target Structure: MainApp (Application target) Dependencies: [HogeFeature, Core] HogeFeature (Static Framework target) Dependencies: [Core] Core (Framework target) Dependencies: None TestHogeFeature (Unit test target) Dependencies: [HogeFeature] Summary I am currently working on a SwiftUI-based project and have encountered an issue where Previews fail to display under specific conditions. Below are the details: Issue In the MainApp scheme, when the code coverage collection setting (Gather coverage for) is enabled, Previews for SwiftUI Views within the HogeFeature (Static Framework) target fail to display correctly. However, the issue is resolved by taking one of the following actions: Change HogeFeature from a Static Framework to a Dynamic Framework. Remove the build setting MACH_O_TYPE: staticlib Disable the Gather coverage setting in the MainApp scheme. I have attached the actual error log from the failed Preview. preview error log Questions Why does this issue occur only when using a Static Framework with code coverage enabled? Is there any way to resolve this issue while maintaining the current configuration (Static Framework with code coverage enabled)? I would appreciate any advice or insights regarding the cause and potential solutions.
0
0
504
Jan ’25
How to use .symbolVariant(.contains: )
I'm getting a weird response from Xcode in trying to use symbolVariant(.contains). I also don't understand why it demands the type cast. What am I doing wrong? Here's the code as text: import SwiftUI let Variants: [SymbolVariants] = [ .circle, .square, .fill, .rectangle, .slash, .none ] func varAvail(_ image: Image) -> [SymbolVariants] { var res: [SymbolVariants] = [] for variant in Variants { if image.symbolVariant(.contains(variant)) as! Bool { res.append(variant) } } }
2
0
357
Jan ’25
CATransaction commit [Crashed: com.apple.root.user-initiated-qos.cooperative]
Description We are developing a app for iOS and iPadOS that involves extensive custom drawing of paths, shapes, texts, etc. To improve drawing and rendering speed, we use CARenderer to generate cached images (CGImage) on a background thread. We adopted this approach based on this StackOverflow post: https://stackoverflow.com/a/75497329/9202699. However, we are experiencing frequent crashes in our production environment that we cannot reproduce in our development environment. Despite months of debugging and seeking support from DTS and the Apple Feedback platform, we have not been able to fully resolve this issue. Our recent crash reports indicate that the crashes occur when calling CATransaction.commit(). Crash traceback The method names in this traceback are mapped to those in the code sample below. The app name has been masked. Crashed: com.apple.root.user-initiated-qos.cooperative 0 MyApp 0x887408 specialized static CAUtils.commitCATransaction() + 4340151304 (<compiler-generated>:4340151304) 1 MyApp 0x887408 specialized static CAUtils.commitCATransaction() + 4340151304 (<compiler-generated>:4340151304) 2 MyApp 0x8874a4 specialized static CAUtils.addDrawingItemsToRenderer(xxx) + 250 (CAUtils.swift:250) 3 MyApp 0x887710 specialized static CAUtils.drawOnCGImageWithCARenderer(xxx) + 267 (CAUtils.swift:267) 4 MyApp 0x8878c0 specialized static CAUtils.drawOnCGImageWithCARendererWithRetry(xxx) + 315 (CAUtils.swift:315) 5 MyApp 0x736294 XXXManager.generateCGImages(xxx) + 570 (XXXManager.swift:570) 6 MyApp 0x73404c closure #1 in XXXManager.updateCachedCGImages(xxx) + 427 (XXXManager.swift:427) 7 libswift_Concurrency.dylib 0x61104 swift::runJobInEstablishedExecutorContext(swift::Job*) + 252 8 libswift_Concurrency.dylib 0x62514 swift_job_runImpl(swift::Job*, swift::SerialExecutorRef) + 144 9 libdispatch.dylib 0x15d8c _dispatch_root_queue_drain + 392 10 libdispatch.dylib 0x16590 _dispatch_worker_thread2 + 156 11 libsystem_pthread.dylib 0x4c40 _pthread_wqthread + 228 12 libsystem_pthread.dylib 0x1488 start_wqthread + 8 Code Sample Below is a sample of our code. While the complete snippet is too long, the issue occurs in addDrawingItemsToRenderer. Please refer to the other methods for completeness and reference purposes. private let transactionLock = NSLock() private let deviceLock = NSLock() private let device = MTLCreateSystemDefaultDevice()! /// This is the method we call from outside. @inline(never) static func drawOnCGImageWithCARenderer( layerRect: CGRect, drawingItems: [DrawingItem] ) -> CGImage? { guard let (texture, renderer) = addDrawingItemsToRenderer( layerRect: layerRect, drawingItems: drawingItems ) else { return nil } renderer.beginFrame(atTime: 0, timeStamp: nil) renderer.render() renderer.endFrame() guard let colorSpace = CGColorSpace(name: CGColorSpace.sRGB), let ciImage = CIImage(mtlTexture: texture, options: [.colorSpace: colorSpace]) else { return nil } let context = CIContext() return context.createCGImage(ciImage, from: ciImage.extent) } /// This is the method will the crash happens @inline(never) fileprivate static func addDrawingItemsToRenderer( layerRect: CGRect, drawingItems: [DrawingItem] ) -> (MTLTexture, CARenderer)? { // We have encapsulated everything related to CALayer and its // associated creations and manipulations within CATransaction // as suggested by engineers from Apple Feedback Portal. beginCATransaction() defer { commitCATransaction() // The crash happens here } let (layer, imageWidth, imageHeight) = addDrawingItemsToLayer(layerRect: layerRect, drawingItems: drawingItems) return createTextureAndRenderer( layer: layer, imageWidth: imageWidth, imageHeight: imageHeight ) } // Below are all internal methods. We have split the method into very // granular parts and marked them as @inline(never) to prevent the // compiler from inlining our code, which may otherwise obscure usage // trackback information in our crash reports. @inline(never) fileprivate static func beginCATransaction() { transactionLock.lock() CATransaction.begin() } @inline(never) fileprivate static func commitCATransaction() { // From our crash report, we believe the crash happens on this line. CATransaction.commit() // It is unlikely that the lock cause the crash as we added it only recently // to ensure that there is only one transaction on our background thread, // and after we added this lock, the crash rate indeed lowered, but still // not fully disappear transactionLock.unlock() } -------------------------------- // The methods below are provided for reference and completeness. While // they may have issues, they do not frequently appear in our crash // reports as the one caused by `CATransaction.commit()` @inline(never) fileprivate static func addDrawingItemsToLayer( layerRect: CGRect, drawingItems: [DrawingItem] ) -> (layer: CALayer, imageWidth: CGFloat, imageHeight: CGFloat) { let layer = CALayer() layer.isGeometryFlipped = SharedAppUtils.isIOS layer.anchorPoint = CGPoint.zero layer.bounds = layerRect layer.masksToBounds = true for drawingItem in drawingItems { // We have thousands or hundred thousands of drawing items to add. // Each drawing item may produce a CALayer, CAShapeLayer or CATextLayer. // This is also why we want to utilise CARenderer to leverage GPU rendering. let sublayerForDrawingItem = drawingItem.createCALayerOrCATextLayerOrCAShapeLayer() layer.addSublayer(sublayerForDrawingItem) } let imageWidth = max(1, layer.frame.size.width * UIScreen.main.scale) let imageHeight = max(1, layer.frame.size.height * UIScreen.main.scale) layer.transform = CATransform3DMakeScale(UIScreen.main.scale, UIScreen.main.scale, 1) layer.frame = .init(origin: .zero, size: .init(width: imageWidth, height: imageHeight)) return (layer, imageWidth, imageHeight) } @inline(never) fileprivate static func createTextureAndRenderer( layer: CALayer, imageWidth: CGFloat, imageHeight: CGFloat ) -> (MTLTexture, CARenderer)? { deviceLock.lock() defer { deviceLock.unlock() } let textureDescriptor = MTLTextureDescriptor.texture2DDescriptor( pixelFormat: .rgba8Unorm, width: Int(imageWidth), height: Int(imageHeight), mipmapped: false ) textureDescriptor.usage = [MTLTextureUsage.shaderRead, .shaderWrite, .renderTarget] guard let texture = device.makeTexture(descriptor: textureDescriptor) else { return nil } let renderer = CARenderer(mtlTexture: texture) renderer.bounds = layer.frame renderer.layer = layer.self return (texture, renderer) }
1
1
494
Jan ’25
Keyboard doesn't close if QuickType bar is open for password auto-fill in SwiftUI when using associated domains.
Description Our app (and sample app) are using associated domains to support deep linking. As an unintended side effect we get full support for auto-filling passwords with the QuickType bar on our login screen. However, after the username and password fields are filled and the user taps the Login button, the keyboard stays on screen. We have tried everything I can think of including @FocusState and UIKit resignFirstResponder, among other things. Our login screen is in a fullscreencover or sheet. When the sheet dismisses the keyboard is still present. In my sample app (and the code below) if I use a navigation stack and push the next view onto the stack, the keyboard closes. I'm not able to provide a useful video because the iOS keyboard closes when focus is in a SecureField. *Note: If we remove the associated domain from our app (and website) the backup iOS password functionality takes over and the keyboard works as expected. Code struct ContentView: View { @State private var name: String = "" @State private var password: String = "" @State private var showLogin = false @FocusState private var isFocused: Bool var body: some View { VStack { Button("Login") { showLogin.toggle() } } .fullScreenCover(isPresented: $showLogin) { VStack { TextField("Enter your name", text: $name) .textFieldStyle(.roundedBorder) .focused($isFocused) SecureField("Enter password", text: $password) .autocapitalization(.none) .autocorrectionDisabled(true) .textContentType(.password) .focused($isFocused) Button("Login") { isFocused = false showLogin = false } .buttonStyle(.borderedProminent) } } } } Steps to Reproduce Launch sample app Tap 'Login' Place keyboard focus in the first text field (name) Keyboard with QuickType bar opens Tap 'Passwords' Create a new password for this login item (choose any username) Passwords will close Tap 'Login' to close the sheet Force close the app Reopen the app Tap 'Login' Place keyboard focus in the first text field (name) Keyboard with QuickType” bar opens Tap the auto-fill password button (password for atomicrobot.com in my case) User name and password fields are filled out Keyboard with QuickType bar is still open; keyboard focus is in "password" field Tap 'Login' Sheet closes, keyboard is still open
Topic: UI Frameworks SubTopic: SwiftUI
1
0
304
Jan ’25
Swift unable to find sound file
Hi everyone, I'm currently facing an issue with AVAudioPlayer in my SwiftUI project. Despite ensuring that the sound file "buttonsound.mp3" is properly added to the project's resources (I dragged and dropped it into Xcode), the application is still unable to locate the file when attempting to play it. Here's the simplified version of the code I'm using: import SwiftUI import AVFoundation struct ContentView: View { var body: some View { VStack { Button("Play sound") { playSound(named: "buttonsound", ofType: "mp3") } } } } func playSound(named name: String, ofType type: String) { guard let soundURL = Bundle.main.url(forResource: name, withExtension: type) else { print("Sound file not found") return } do { let audioPlayer = try AVAudioPlayer(contentsOf: soundURL) audioPlayer.prepareToPlay() audioPlayer.play() } catch let error { print("Error playing sound: \(error.localizedDescription)") } }
8
0
2.7k
Jan ’25
iOS 18.3 Beta 1 Screen Time tracking got worse?
Hi there, I am flagging for extra attention that it feels to me that something feels extra off about Screen Time tracking in iOS 18.3 Beta. There's been many days now where I can't reconcile the time spent (it's much higher than expected - by multiple hours). Feedback is here with an image: FB16270245. Not sure if happens on Beta 2 - just upgraded.
2
1
706
Jan ’25
ProgressView does not complete on long running tasks
My project implements a way of copying files via drag and drop on MacOS. I use the ProgressView to show the progress of the copy operation. Conveniently Progress is used to interact with the NSItemProvider and the ProgressView. On longer running tasks (still seconds) the ProgressView is updated at first, but always stops before completion. The Progress Object has completed on the other hand, but it seems that the last update ist not affected. I am now using a timer to update the view, but that is somewhat a workaround. This is the code that is in the view. struct DragView: View { @State private var progress: Progress! var body: some View { ProgressView(value: progress.fractionCompleted, total: 1) } } Any hints into how I can get this to work? I am using Xcode 16.2
Topic: UI Frameworks SubTopic: SwiftUI
3
0
286
Jan ’25
SwiftUI Popover clips in iOS18
When you try to present medium height popover from the bottom of iPhone view then popover is clipped in iOS18 but works in old devices Sample code Button("Show Popover") { showPopover.toggle() } .popover( isPresented: $showPopover, arrowDirection: arrowDirection ) { conent } Result
5
0
1.9k
Jan ’25