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?
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.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Created
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) ?
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.
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
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 ?
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.
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?
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
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
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
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.
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.
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
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.
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
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?
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.
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?
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.
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