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

Image not rendering on some devices
Hi, new developer here. I have an issue where an image I have on app is not showing up on some devices. The image is: Resources/Assets/logo: I am using it in my app like: ZStack { Color.white .ignoresSafeArea() VStack { Spacer() Image("logo") Spacer() Text(dateString) .font(.custom("LinLibertine", size: 17)) .fontWeight(.bold) .tracking(5) .padding(.bottom, 50) } } The image appears fine on all simulators. And also on my real device iPad with A14. But when I run it on iPhone 8 or iPad Air M4, it shows empty space in place of image. I tried many different options like: Image("logo") .renderingMode(.original) .resizable() .scaledToFit() frame(width: 300) .background(Color.red.opacity(0.3)) But nothing works. What can be the issue?
2
1
121
3w
How to avoid this thread priority inversions ?
Context: Xcode 16.4, Appkit In a windowController, I need to create and send a mouseDown event (newMouseDownEvent). I create the event with: let newMouseDownEvent = NSEvent.mouseEvent( with: .leftMouseDown, location: clickPoint, // all other fields I also need to make window key and front, otherwise the event is not handled.   func simulateMouseDown() { self.window?.makeFirstResponder(self.window) self.calepinFullView.perform(#selector(NSResponder.self.mouseDown(with:)), with: newMouseDownEvent!) }   As I have to delay the call( 0.5 s), I use asyncAfter: DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, qos: .userInteractive) { self.simulateMouseDown() }   It works as intended, but that generates the following (purple) warning at runtime: [Internal] Thread running at User-interactive quality-of-service class waiting on a lower QoS thread running at Default quality-of-service class. Investigate ways to avoid priority inversions I have tried several solutions, change qos in await: DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, qos: ..default) call from a DispatchQueue let interactiveQueue = DispatchQueue.global(qos: .userInteractive) interactiveQueue.async { self.window?.makeFirstResponder(self.window) self.calepinFullView.perform(#selector(NSResponder.self.mouseDown(with:)), with: newMouseDownEvent!) } But that's worse, it crashes with the following error: FAULT: NSInternalInconsistencyException: -[HIRunLoopSemaphore wait:] has been invoked on a secondary thread; the problem is likely in a much shallower frame in the backtrace; { NSAssertFile = "HIRunLoop.mm"; NSAssertLine = 709; }   How to eliminate the priority inversion risk (not just silencing the warning) ?
2
0
164
3w
WidgetKit (systemMedium) SwiftUI Text: auto-fit to the largest font size without “…”
Hi all, I’m stuck on a WidgetKit/SwiftUI layout issue. I have a systemMedium widget that shows a block of text. What I want is simple: The text should be as large as possible But it must always fully fit inside the widget No ellipsis (“…”) Short text → big font Longer text → shrink only as much as needed The problem: when I try to make the font larger, the widget often shows only a couple of words and then “…” (or it looks like it’s truncating/clipping), even though I’m using multiline text (lineLimit(nil) etc.). If I keep a small fixed font size, the entire text shows fine — so the input string isn’t truncated. I tried a few approaches: ViewThatFits seeing which font size fits minimumScaleFactor Measuring with NSAttributedString.boundingRect + binary search to calculate the biggest font size that should fit But WidgetKit still behaves inconsistently and I can’t get a reliable “largest size that fits” result. Is there a recommended, production-safe way to do this in WidgetKit? Also: can a SwiftUI Text still end up showing “…” in a widget even with .lineLimit(nil) when it’s constrained vertically? Thanks in advance — any pointers or known patterns would really help.
0
0
86
3w
SwiftUI mysterious behavior
Hello dear developers! Recently, I stumbled upon some really strange behavior of SwiftUI and I’m very curious why it works this way struct ContentView: View { @State private var title: String? @State private var isSheetPresented: Bool = false var body: some View { Button("Hello, world!") { title = "Sheet title" isSheetPresented = true } .sheet(isPresented: $isSheetPresented, content: { if let title { Text(title) } else { EmptyView() } }) } } Why in this case when we tap the button and sheet comes in we go to the branch else even though we set title before isSheetPresented but it still somehow nil But what really drive me crazy is that if we change a little bit code to this: I just added another @State property 'number' and use it as the Button's title. In this scenario it works 😃 and Text in the sheet view appearing struct ContentView: View { @State private var title: String? @State private var number = 0 @State private var isSheetPresented = false var body: some View { Button("\(number)") { title = "Sheet title" number += 0 isSheetPresented = true } .sheet(isPresented: $isSheetPresented, content: { if let title { Text(title) } else { EmptyView() } }) } } Is this somehow related to what happens under the hood like View Tree and Render Tree (Attribute Graph)? Maybe because ContentView’s body doesn't capture title it cannot be stored in the Render Tree so it always would have the initial value of nil? if there are any well-informed folks here, please help me figure out this mystery, I’d appreciate it!!! p.s. Don’t get me wrong. Im not interested in how to make it work. I’m interested in why this doesn’t work and what really happens under the hood that led to this result
2
0
140
3w
Whimsical tooltips behaviour in popover (Appkit)
In this app I use tooltips extensively. They work perfectly well, except in a popover where they may appear or not (just some flash and immediately disappear). In the popover there are 12 colour buttons, each with its own tracking area and 3 control buttons, with their tracking areas. Here when it works, hovering over "C" button or "Annuler" button: But then, when I move to another colour button, a few 2 or 3 may work, but most don't display their tooltip at all. I know that the tooltip is set because I replicate the message in a help line at the bottom of the screen and this line always update: Let messageForColor = "Choisir la couleur…" if button.isEnabled { // show tooltip button.toolTip = messageForColor } else { button.toolTip = nil } if button.isEnabled { // Shows helpline at the bottom of screen button.helpMessage = messageForColor } Maybe it comes from some useDefault (I modified NSInitialTool TipDelay and I'm not sure I have reset to the default value) I noted that if I wait for 10 seconds or so (keeping the popover opened), everything seems to work properly again. Just as if there was some lengthy initialisation going on. So questions: Is there a known issue of Tooltips in a popover ? Are there other parameters to set in userDefaults to avoid immediate disparition of the tooltip in popover ? How to reset the factory setting for the UserDefaults in the app ?
5
0
442
3w
SwiftUI List: observable reference types not deallocated immediately after refresh
Hello 👋 I ran into a SwiftUI lifecycle gotcha while debugging a List with .refreshable I share the code used to reproduce the issue @Observable final class CounterModel: Identifiable { let id: String var title: String var value: Int init(id: String, title: String, value: Int = 0) { self.id = id self.title = title self.value = value } deinit { print("deinit", title) } } @Observable final class ObservableCountersStore { var counters: [CounterModel] = [ .init(id: "1", title: "A"), .init(id: "2", title: "B"), .init(id: "3", title: "C") ] func refresh() async { try? await Task.sleep(nanoseconds: 300_000_000) counters = [.init(id: "4", title: "D")] } } struct ObservableCountersListView: View { @State private var store = ObservableCountersStore() var body: some View { List { ForEach(store.counters) { counter in ObservableCounterRow(counter: counter) } } .refreshable { await store.refresh() } } } struct ObservableCounterRow: View { let counter: CounterModel var body: some View { Text(counter.title) } } Observation: After calling refresh(), only some of the previous CounterModel only one CounterModel is deallocated immediately. Others are retained This doesn’t look like a leak, but it made me realize that passing observable reference types directly into List rows leads to non-deterministic object lifetimes, especially with .refreshable. Posting this as a gotcha — curious if this matches intended behavior or if others have run into the same thing.
2
0
190
3w
iOS 26.0+: sceneDidBecomeActive / applicationDidBecomeActive fires during Lock button press while app is active
Hi all, I’m seeing a lifecycle behavior change on iOS 26.0 (and up). While my app is in the foreground and active, pressing the hardware Lock button triggers didBecomeActive callbacks/notifications even though the app is transitioning away from active state. I’m observing this sequence: willResignActive didBecomeActive willResignActive didEnterBackground This happens for: • UISceneDelegate.sceneDidBecomeActive(:) • UIApplicationDelegate.applicationDidBecomeActive(:) • UIApplication.didBecomeActiveNotification On iOS 18 (same app, same code) I do not see didBecomeActive in the middle of locking/backgrounding. Problem is reproduced on totally new project. I would expect a normal transition to background: • willResignActive → didEnterBackground …and no extra didBecomeActive between them. I have “became active” logic (refresh UI/state, resume timers, analytics). On iOS 26.0 this logic runs unexpectedly during locking, causing unnecessary work and incorrect state transitions. Is this callback ordering expected on iOS 26.0 when pressing the Lock button? If expected, what’s the recommended way to detect a “real” activation (and avoid transient didBecomeActive during locking/backgrounding)? If this is a regression, is there a known workaround or best practice?
Topic: UI Frameworks SubTopic: UIKit Tags:
1
2
220
3w
macOS 26.3 RC breaks all borderless window interactions
After updating to macOS 26.3 Release Candidate, all interactions for borderless windows are no longer working. In macOS 26.3 Beta, borderless windows behaved correctly: • Mouse clicks were received normally • Window dragging worked as expected • Interaction logic was fully functional However, in macOS 26.3 RC, all of the above behaviors are broken: • Click events are not delivered • Windows cannot be moved or interacted with • The issue affects all borderless windows This is a regression from the Beta build and appears to be system-level, not app-specific. Environment: • macOS: 26.3 RC • Window type: borderless / frameless windows • Status in 26.3 Beta: working correctly • Status in 26.3 RC: completely broken Could Apple confirm whether this is a known issue or an intentional behavior change in 26.3 RC? If this is a , is there a recommended workaround before the final release? Thanks.
Topic: UI Frameworks SubTopic: AppKit
2
0
174
3w
Can I disable a SwiftUI View from being a draggable source, but still leave it enabled as a dropDestination?
My app has a collection of Cell Views. some of the views' model objects include a Player, and others do not. I want to use drag and drop to move a player from one cell to another. I only want cells that contain a player to be valid drag sources. All cells will be valid drop destinations. When I uncomment the .disabled line both drag and drop become disabled. Is it possible to keep a view enabled as a dropDestination but disabled as a draggable source? VStack { Image("playerJersey_red") if let player = content.player { Text(player.name) } } .draggable(content) // .disabled(content.player == nil) .dropDestination(for: CellContent.self) { items, location in One thing I tried was to wrap everything in a ZStack and put a rectangle with .opacity(0.02) above the Image/Text VStack. I then left draggable modifying my VStack and moved dropDestination to the clear rectangle. This didn't work as I wasn't able to initiate a drag when tapping on the rectangle. Any other ideas or suggestions? thanks
4
0
183
3w
Transperent title bar changed to gray when refocus
Hello, I'm trying to create game in macos with transperent titlebar. The title bar t stay transperent when I click inside, but changed to gray when the window resize or get out of focus. How can I make it stay transperent all the time? I did all of this: window.styleMask.insert(.fullSizeContentView) window.titlebarAppearsTransparent = true window.titlebarSeparatorStyle = .none window.titleVisibility = .hidden window.isMovableByWindowBackground = true window.isOpaque = false window.backgroundColor = .black in the swiftUI view created zstack that start with: var body: some View { ZStack { Color.black.ignoresSafeArea() help please :) Thanks.
Topic: UI Frameworks SubTopic: General
2
0
171
3w
How do i use dynamic data for my SwiftUI ScrollView without destroying performance?
Currently i am trying really hard to create experience like the Apple fitness app. So the main view is a single day and the user can swipe between days. The week would be displayed in the toolbar and provide a shortcut to scroll to the right day. I had many attempts at solving this and it can work. You can create such an interface with SwiftUI. However, changing the data on every scroll makes limiting view updates hard and additionally the updates are not related to my code directly. Instruments show me long updates, but they belong to SwiftUI and all the advice i found does not apply or help. struct ContentView: View { @State var journey = JourneyPrototype(selection: 0) @State var position: Int? = 0 var body: some View { ScrollView(.horizontal) { LazyHStack(spacing: 0) { ForEach(journey.collection, id: \.self) { index in Listing(index: index) .id(index) } } .scrollTargetLayout() } .scrollTargetBehavior(.paging) .scrollPosition(id: $position) .onChange(of: position) { oldValue, newValue in journey.selection = newValue ?? 0 journey.update() } .onScrollPhaseChange { oldPhase, newPhase in if newPhase == .idle { journey.commit() } } } } struct Listing: View { var index: Int var body: some View { List { Section { Text("Title") .font(.largeTitle) .padding() } Section { Text("\(index)") .font(.largeTitle) .padding() } Section { Text("1 ") Text("2 ") Text("3 ") Text("4 ") Text("5 ") Text("6 ") } } .containerRelativeFrame(.horizontal) } } @Observable class JourneyPrototype { var selection: Int var collection: [Int] var nextUp: [Int]? init(selection: Int) { self.selection = selection self.collection = [selection] Task { self.collection = [-2,-1,0,1,2] } } func update() { self.nextUp = [ self.selection - 2, self.selection - 1, selection, self.selection + 1, self.selection + 2 ] } func commit() { self.collection = self.nextUp ?? self.collection self.nextUp = nil } } #Preview { ContentView() } There are some major Problem with this abstracted prototype ScrollView has no good trigger for the update, because if i update on change of the position, it will update much more than once. Thats why i had to split calculation and applying the diff The LazyHStack is not optimal, because there are only 5 View in the example, but using HStack breaks the scrollPosition Each scroll updates all List, despite changing only 2 numbers in the array. AI recommended to append and remove, which does nothing about the updates. In my actual Code i do this with Identifiable data and the Problem is the same. So the data itself is not the problem? Please consider, this is just the rough prototype to explain the problem, i am aware that an array of Ints is not ideal here, but the problem is the same in Instruments and much shorter to post. Why am i posting this? Scrolling through dynamic data is required for many apps, but there is no proper solution to this online. Github and Blogs are fine with showing a progress indicator and letting the user wait, some probably perform worse than this prototype. Other solutions require UIKit like using a UIPageViewController. But even using this i run in small hitches related to layout. Important consideration, my data for the scrollview is too big to be calculated upfront. 100 years of days that are calculated for my domain logic take too long, so i have no network request, but the need to only act on a smaller window of data. Instruments shows long update for one scroll action tested on a iPhone SE 2nd generation ListRepresentable has 7 updates and takes 17ms LazySubViewPlacements has 2 updates and takes 8ms Other long updates are too verbose to include I would be very grateful for any help.
0
0
66
3w
iOS 26: hidesSharedBackground does not work for backBarButtonItem
What works let backButton = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil) backButton.hidesSharedBackground = true self.navigationItem.rightBarButtonItem = backButton // or self.navigationItem.leftBarButtonItem = backButton What doesn't work let backButton = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil) backButton.hidesSharedBackground = true self.navigationItem.backBarButtonItem = backButton I've tried setting this property on all possible permutations and combinations e.g. Inside navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) and pushViewController(_ viewController: UIViewController, animated: Bool) of a custom UINavigationController to make sure. Expected vs Actual behavior Setting hidesSharedBackground = true should remove the glass background from both regular bar button items and back bar button items but it has no effect on backBarButtonItem. Additional context I’m aware of the UIDesignRequiresCompatibility Info.plist key, but I’m looking for a programmatic solution if there is one. The goal is to remove the glass background from back buttons.
1
1
166
3w
SwiftUI onChange fires twice when filtering data from @Observable store
Hi all, I’m running into a “double update” effect in SwiftUI when using the @Observable with @State. I’m trying to understand whether this is expected behavior, a misuse on my side, or a potential bug. Setup I have an observable store using the Observation macro: @Observable class AlbumStore { var albums: [Album] = [ Album(id: "1", title: "Album 1", author: "user1"), Album(id: "2", title: "Album 2", author: "user1"), Album(id: "3", title: "Album 3", author: "user1"), Album(id: "4", title: "Album 4", author: "user1"), Album(id: "5", title: "Album 5", author: "user1"), Album(id: "6", title: "Album 6", author: "user1") ] func addAlbum(_ album: Album) { albums.insert(album, at: 0) } func removeAlbum(_ album: Album) { albums.removeAll(where: { $0 == album }) } } In my view, I inject it via @Environment and also keep some local state: @Environment(AlbumStore.self) var albumStore @State private var albumToAdd: Album? I derive a computed array that depends on both the environment store and local state: private var filteredAlbums: [Album] { let albums = albumStore.albums.filter { album in if let albumToAdd { return album.id != albumToAdd.id } else { return true } } return albums } View usage Inside a horizontal ScrollView / LazyHStack, I observe changes to filteredAlbums: @ViewBuilder private func carousel() -> some View { GeometryReader { proxy in let itemWidth: CGFloat = proxy.size.width / 3 let sideMargin = (proxy.size.width - itemWidth) / 2 ScrollView(.horizontal, showsIndicators: false) { LazyHStack(spacing: 20) { ForEach(filteredAlbums, id: \.id) { album in albumItem(album: album) .frame(width: itemWidth) .scrollTransition(.interactive, axis: .horizontal) { content, phase in content .scaleEffect(phase.isIdentity ? 1.0 : 0.8) } } } .scrollTargetLayout() } .scrollTargetBehavior(.viewAligned(limitBehavior: .always)) .scrollPosition(id: $carouselScrollID, anchor: .center) .contentMargins(.horizontal, sideMargin, for: .scrollContent) .onChange(of: filteredAlbums) { old, new in print("filteredAlbums id: \(new.map { $0.id })") } } } Triggering the update When I add a new album, I do: albumToAdd = newAlbum albumStore.addAlbum(newAlbum) Expected behavior Since filteredAlbums explicitly filters out albumToAdd, I expect the result to remain unchanged. Actual behavior I consistently get two onChange callbacks, in this order: filteredAlbums id: ["E852E42A-AAEC-4360-A6A6-A95752805E2E", "1", "2", "3", "4", "5", "6"] filteredAlbums id: ["1", "2", "3", "4", "5", "6"] This suggests: The AlbumStore update (albums.insert) is observed first. The @State update (albumToAdd) is applied later. As a result, filteredAlbums is recomputed twice with different dependency snapshots. On a real iPad device, this also causes a visible scroll position jump. In the simulator, the jump is not visually observable; however, the onChange(of: filteredAlbums) callback still fires twice with the same sequence of values, indicating that the underlying state update behavior is identical. Strange observations This does not happen with ObservableObject If I replace @Observable with a classic ObservableObject + @Published: class OBAlbumStore: ObservableObject { @Published var albums: [Album] = [ Album(id: "1", title: "Album 1", author: "user1"), Album(id: "2", title: "Album 2", author: "user1"), Album(id: "3", title: "Album 3", author: "user1"), Album(id: "4", title: "Album 4", author: "user1"), Album(id: "5", title: "Album 5", author: "user1"), Album(id: "6", title: "Album 6", author: "user1") ] func addAlbum(_ album: Album) { albums.insert(album, at: 0) } func removeAlbum(_ album: Album) { albums.removeAll(where: { $0 == album }) } } …and inject it with @EnvironmentObject, the double update disappears. Removing GeometryReader also avoids the issue If I remove the surrounding GeometryReader and hardcode sizes: @ViewBuilder private func carousel() -> some View { // GeometryReader { proxy in let itemWidth: CGFloat = 400 let sideMargin: CGFloat = 410 ScrollView(.horizontal, showsIndicators: false) { LazyHStack(spacing: 20) { ForEach(filteredAlbums, id: \.id) { album in albumItem(album: album) .frame(width: itemWidth) .scrollTransition(.interactive, axis: .horizontal) { content, phase in content .scaleEffect(phase.isIdentity ? 1.0 : 0.8) } } } .scrollTargetLayout() } .scrollTargetBehavior(.viewAligned(limitBehavior: .always)) .scrollPosition(id: $carouselScrollID, anchor: .center) .contentMargins(.horizontal, sideMargin, for: .scrollContent) .onChange(of: filteredAlbums) { old, new in print("filteredAlbums id: \(new.map { $0.id })") } // } } …the double onChange no longer occurs. Questions Is this update ordering expected when using @Observable and @State? Does Observation intentionally propagate environment changes before local state updates? Is GeometryReader forcing an additional evaluation pass that exposes this ordering? Is this a known limitation / bug compared to ObservableObject? I want to understand why this behaves differently under Observation. Thanks in advance for any insights 🙏 Full Project Link
2
0
187
3w
Custom NSWindow styleMask behavior changed/broken resulting in unresizable or non-responsive windows in macOS Tahoe 26.3 RC
NSWindow objects with custom styleMask configurations seem to behave erratically in macOS Tahoe 26.3 RC. For example an NSWindow is not resizable after issuing .styleMask.remove(.titled) or some NSWindow-s become totally unresponsive (the NSWindow becomes transparent to mouse events) with custom styleMask-s. This is a radical change compared to how all previous macOS versions or the 26.3 beta3 worked and seriously affects apps that might use custom NSWindows - this includes some system utilities, OSD/HUD apps etc, actually breaking some apps. Such fundamental compatibility altering changes should not be introduced in an RC stage (if this is intentional and not a bug) imho.
Topic: UI Frameworks SubTopic: AppKit Tags:
9
6
3.6k
3w
Same Color in View and colorEffect shader argument produce different results
Opened feedback item FB21877364. Context I have the following Metal shader, which replaces one color with another. [[ stitchable ]] half4 recolor( float2 position, half4 currentColor, half4 from, half4 to ) { if (all(currentColor == from)) return to; return currentColor; } Given this SwiftUI view: let shader = ShaderLibrary.recolor(.color(.red), .color(.green)) Color.red .colorEffect(shader) I get a red rectangle instead of the expected green one. Note that this works on both dynamic and non-dynamic colors. Note that this sometimes works with some colors, which is very inconvenient when trying to figure out what's going on. Did I miss something? I would've expected the shader to work with colors the same way. Issue To really highlight the issue, here's another test case. I'll define #94877E in an Asset Catalog as example and check the RGB values using the Digital Color Meter app in "Display native values" mode. We'll use the following shader to determine how colorEffect receives colors: [[ stitchable ]] half4 test( float2 position, half4 currentColor, half4 color ) { return color; } The following view yields "R: 0.572, G: 0.531, B: 0.498". Color.example While this one yields "R: 0.572, G: 0.531, B: 0.499". let shader = ShaderLibrary.test(.color(Color.example)) Color.white.colorEffect(shader) I would expect them to match.
Topic: UI Frameworks SubTopic: SwiftUI
0
0
22
3w
Password AutoFill BUG
When using the Password AutoFill feature, after entering a password and navigating to another page, a system prompt appears asking whether to save the password to the keychain (as shown in the figure). If this prompt is not dismissed and the app is moved to the background, then brought back to the foreground, the prompt automatically disappears. However, after this occurs, all input fields within the app become unresponsive to keyboard input—no keyboard will appear when tapping any text field. The only way to restore keyboard functionality is to force-quit the app and relaunch it. How can this issue be resolved?
0
0
115
3w
Layout issue using .strokeBorder modifier
Hello, Developers! While writing custom view modifier I ran into unexpected behavior of .strokeBorder modifier. The underlying content seem to be “bleeding” outside of the stroke border edges, even though they share the exact same shape for their layout. This issue relevant for both Xcode Previews and on-device testing. Maybe someone has experienced this issue before, I'd be glad to see your opinion on this matter.
1
0
135
3w
Conditional Modifiers *if available*
I am adopting some of the new glass UI, but having to duplicate a lot of code to maintain support for previous UI systems in macOS. An example: if #available(macOS 26.0, *) { VStack { /*some 40+ lines of code clipped here for brevity*/ } .cueButtons() .cueStyleGlass() } else { VStack { /*identical 40+ lines of code clipped here for brevity*/ } .cueButtons() .cueStyle() } If I try to use conditional modifiers as indicated here: extension View { func cueStyle(font: Font = .system(size: 45)) -> some View { if #available(macOS 26.0, *) { modifier(GlassCueStyle(font: font)) } else { modifier(CueStyle(font: font)) } } } I get this error: Conflicting arguments to generic parameter 'τ_1_0' ('ModifiedContent<Self, GlassCueStyle>' vs. 'ModifiedContent<Self, CueStyle>') Is there a better way to do this?
3
0
235
3w
App Launchscreen Size NOT Correct on iPadOS 26
Hello, We’re seeing an iPad-specific Launch Screen issue related to multitasking window sizes. Environment Device: iPad (iPadOS 26) Device orientation: Landscape App is launched in a small window where the app window is portrait-shaped (width < height) Issue When the iPad is in landscape but the app is launched as a portrait-shaped small window, the LaunchScreen.storyboard appears to be rendered/layouted as landscape, not matching the actual window geometry. As a result, the Launch Screen content is clipped / partially missing (we see blank/empty area at the bottom during launch). After the app finishes launching, our first view controller uses the correct window size and the UI looks fine — the problem is mainly during the Launch Screen phase. What we checked LaunchScreen.storyboard uses Auto Layout and is expected to adapt to screen/window size. This only reproduces when the device orientation and the app window aspect ratio don’t match (landscape device + portrait-shaped app window, or vice versa). When device orientation and window shape are aligned, the Launch Screen displays correctly. Question Is it expected that iPadOS renders LaunchScreen.storyboard based on the interface orientation / size class rather than the actual window bounds in multitasking scenarios? If not expected, what is the recommended way to ensure the Launch Screen matches the app’s actual window size/aspect ratio at launch (without using code, since Launch Screen is static)? Are there any additional diagnostics or recommended steps to help us investigate and confirm the root cause (e.g., specific logs, APIs/values to capture at launch such as UIWindowScene bounds, interfaceOrientation, size classes, or any guidance on how Launch Screen snapshots are chosen/cached in multitasking)? Thank you.
0
0
153
3w
Can TextField handle undo?
I'm struggling to understand whether TextField handles undo by itself, or how to properly handle it myself. In a macOS app with a SwiftUI lifecycle, in a DocumentGroup scene, I'm using both TextEditors and Textfields. The text editors handle undo out of the box, with undo coalescing. The text fields seem not to. However, on occasion, they do create undo points, leaving me confused as to what conditions are needed for that to happen. Is there a way to reliably get text fields to handle undo on their own? Or, how should I implement typing undo, including undo coalescing, manually?
Topic: UI Frameworks SubTopic: SwiftUI
9
0
187
3w