In my code I use a binding that use 2 methods to get and get a value. There is no problem with swift 5 but when I swift to swift 6 the compiler fails :
Here a sample example of code to reproduce the problem :
`import SwiftUI
struct ContentView: View {
@State private var isOn = false
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
Text("Hello, world!")
Toggle("change it", isOn: Binding(get: getValue, set: setValue(_:)))
}
.padding()
}
private func getValue() -> Bool {
isOn
}
private func setValue(_ value: Bool) {
isOn = value
}
}`
Xcode compiler log error :
1. Apple Swift version 6.1.2 (swiftlang-6.1.2.1.2 clang-1700.0.13.5) 2. Compiling with the current language version 3. While evaluating request IRGenRequest(IR Generation for file "/Users/xavierrouet/Developer/TestCompilBindingSwift6/TestCompilBindingSwift6/ContentView.swift") 4. While emitting IR SIL function "@$sSbScA_pSgIeAghyg_SbIeAghn_TR". for <<debugloc at "<compiler-generated>":0:0>>Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var LLVM_SYMBOLIZER_PATH` to point to it):
0 swift-frontend 0x000000010910ae24 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 56
1 swift-frontend 0x0000000109108c5c llvm::sys::RunSignalHandlers() + 112
2 swift-frontend 0x000000010910b460 SignalHandler(int) + 360
3 libsystem_platform.dylib 0x0000000188e60624 _sigtramp + 56
4 libsystem_pthread.dylib 0x0000000188e2688c pthread_kill + 296
5 libsystem_c.dylib 0x0000000188d2fc60 abort + 124
6 swift-frontend 0x00000001032ff9a8 swift::DiagnosticHelper::~DiagnosticHelper() + 0
7 swift-frontend 0x000000010907a878 llvm::report_fatal_error(llvm::Twine const&, bool) + 280
8 swift-frontend 0x00000001090aef6c report_at_maximum_capacity(unsigned long) + 0
9 swift-frontend 0x00000001090aec7c llvm::SmallVectorBase::grow_pod(void*, unsigned long, unsigned long) + 384
10 swift-frontend 0x000000010339c418 (anonymous namespace)::SyncCallEmission::setArgs(swift::irgen::Explosion&, bool, swift::irgen::WitnessMetadata*) + 892
11 swift-frontend 0x00000001035f8104 (anonymous namespace)::IRGenSILFunction::visitFullApplySite(swift::FullApplySite) + 4792
12 swift-frontend 0x00000001035c876c (anonymous namespace)::IRGenSILFunction::visitSILBasicBlock(swift::SILBasicBlock*) + 2636
13 swift-frontend 0x00000001035c6614 (anonymous namespace)::IRGenSILFunction::emitSILFunction() + 15860
14 swift-frontend 0x00000001035c2368 swift::irgen::IRGenModule::emitSILFunction(swift::SILFunction*) + 2788
15 swift-frontend 0x00000001033e7c1c swift::irgen::IRGenerator::emitLazyDefinitions() + 5288
16 swift-frontend 0x0000000103573d6c swift::IRGenRequest::evaluate(swift::Evaluator&, swift::IRGenDescriptor) const + 4528
17 swift-frontend 0x00000001035c15c4 swift::SimpleRequest<swift::IRGenRequest, swift::GeneratedModule (swift::IRGenDescriptor), (swift::RequestFlags)17>::evaluateRequest(swift::IRGenRequest const&, swift::Evaluator&) + 180
18 swift-frontend 0x000000010357d1b0 swift::IRGenRequest::OutputType swift::Evaluator::getResultUncached<swift::IRGenRequest, swift::IRGenRequest::OutputType swift::evaluateOrFatalswift::IRGenRequest(swift::Evaluator&, swift::IRGenRequest)::'lambda'()>(swift::IRGenRequest const&, swift::IRGenRequest::OutputType swift::evaluateOrFatalswift::IRGenRequest(swift::Evaluator&, swift::IRGenRequest)::'lambda'()) + 812
19 swift-frontend 0x0000000103576910 swift::performIRGeneration(swift::FileUnit*, swift::IRGenOptions const&, swift::TBDGenOptions const&, std::__1::unique_ptr<swift::SILModule, std::__1::default_deleteswift::SILModule>, llvm::StringRef, swift::PrimarySpecificPaths const&, llvm::StringRef, llvm::GlobalVariable**) + 176
20 swift-frontend 0x0000000102f61af0 generateIR(swift::IRGenOptions const&, swift::TBDGenOptions const&, std::__1::unique_ptr<swift::SILModule, std::__1::default_deleteswift::SILModule>, swift::PrimarySpecificPaths const&, llvm::StringRef, llvm::PointerUnion<swift::ModuleDecl*, swift::SourceFile*>, llvm::GlobalVariable*&, llvm::ArrayRef<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator>>) + 156
21 swift-frontend 0x0000000102f5d07c performCompileStepsPostSILGen(swift::CompilerInstance&, std::__1::unique_ptr<swift::SILModule, std::__1::default_deleteswift::SILModule>, llvm::PointerUnion<swift::ModuleDecl*, swift::SourceFile*>, swift::PrimarySpecificPaths const&, int&, swift::FrontendObserver*) + 2108
22 swift-frontend 0x0000000102f5c0a8 swift::performCompileStepsPostSema(swift::CompilerInstance&, int&, swift::FrontendObserver*) + 1036
23 swift-frontend 0x0000000102f5f654 performCompile(swift::CompilerInstance&, int&, swift::FrontendObserver*) + 1764
24 swift-frontend 0x0000000102f5dfd8 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 3716
25 swift-frontend 0x0000000102ee20bc swift::mainEntry(int, char const**) + 5428
26 dyld 0x0000000188a86b98 start + 6076
Using Xcode 16.4 / Mac OS 16.4
SwiftUI
RSS for tagProvide views, controls, and layout structures for declaring your app's user interface using SwiftUI.
Posts under SwiftUI tag
200 Posts
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Hi everyone,
I’m working on a screen that uses a single SwiftUI List composed of:
a top block (statistics, month picker, year selector, total, Entrata/Uscita picker).
a list of transactions grouped by day, each group inside its own Section.
each row is a fully custom card with rounded corners (RoundedCornerShape)
I’m correctly removing all separators using:
.listRowSeparator(.hidden)
.listSectionSeparator(.hidden)
.scrollContentBackground(.hidden)
.listStyle(.plain)
Each row is rendered like this:
TransazioneSwipeRowView(...)
.listRowInsets(EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16))
.listRowBackground(Color.clear)
However, I still see thin horizontal lines appearing between:
the search bar and the top block
the top block and the start of the list
between rows inside the grouped section
sometimes at the bottom of a Section
These lines are NOT:
Divider()
system separators
backgrounds
row borders
They seem to be “ghost lines” automatically generated by SwiftUI’s List when multiple consecutive rows or sections are present.
Goal
I want to remove these lines completely while keeping:
native SwiftUI List
native scroll behavior
swipe-to-delete support
grouping by Section
custom card-like rows with rounded corners
transparent backgrounds
What I already tried
.plain, .grouped, .insetGrouped list styles
.listRowSeparator(.hidden) and .listSectionSeparator(.hidden)
.scrollContentBackground(.hidden)
clearing all backgrounds
adjusting/removing all padding and insets
Spacer(minLength: 0) experiments
rebuilding the layout using ScrollView + LazyVStack
(works perfectly — no lines — BUT loses native swipe-to-delete)
There are no Divider() calls anywhere, and no background colors producing borders.
Question
Is this a built-in behavior of SwiftUI’s List in .plain style when using multiple custom rows,
or is there an officially supported way to eliminate these lines entirely?
Is there a recommended combination of modifiers to achieve:
a List with grouped Sections
fully custom rows with rounded backgrounds
absolutely no horizontal separators, even in the empty spaces between sections?
Any guidance, documented workarounds, WWDC references, or official recommendations would be greatly appreciated.
Thanks in advance!
Hello everyone!
I found a weird behavior with the animation of Menucomponent on iOS 26.1
When the menu disappear the animation is very glitchy
You can find here a sample of code to reproduce it
@available(iOS 26.0, *)
struct MenuSample: View {
var body: some View {
GlassEffectContainer {
HStack {
Menu {
Button("Action 1") {}
Button("Action 2") {}
Button("Delete", role: .destructive) {}
} label: {
Image(systemName: "ellipsis")
.padding()
}
Button {} label: {
Image(systemName: "xmark")
.padding()
}
}
.glassEffect(.clear.interactive())
}
}
}
@available(iOS 26.0, *)
#Preview {
MenuSample()
.preferredColorScheme(.dark)
}
I did two videos:
iOS 26.0
iOS 26.1
Thanks for your help
I want to support Genmoji input in my SwiftUI TextField or TextEditor, but looking around, it seems there's no SwiftUI only way to do it?
If none, it's kind of disappointing that they're saying SwiftUI is the path forward, but not updating it with support for new technologies.
Going back, does this mean we can only support Genmoji through UITextField and UIViewRepresentable? or there more direct options?
Btw, I'm also using SwiftData for storage.
I’m stuck with repeated production crashes in my SwiftUI app and I can’t make sense of the traces on my own.
The symbolicated reports show the same pattern:
Crash on com.apple.CFNetwork.LoaderQ with EXC_BAD_ACCESS / PAC failure
Always deep in CFNetwork, most often in
URLConnectionLoader::loadWithWhatToDo(NSURLRequest*, _CFCachedURLResponse const*, long, URLConnectionLoader::WhatToDo)
No frames from my code, no sign of AuthManager or tokens.
What I’ve tried:
Enabled Address Sanitizer,
Malloc Scribble,
Guard Malloc,
Zombies.
Set CFNETWORK_DIAGNOSTICS=3 and collected Console logs.
Stress-tested the app (rapid typing, filter switching, background/foreground, poor network with Network Link Conditioner).
Could not reproduce the crash locally.
So far:
Logs show unrelated performance faults (I/O on main thread, CLLocationManager delegate), but no obvious CFNetwork misuse.
My suspicion is a URLSession lifetime or delegate/auth-challenge race, but I can’t confirm because I can’t trigger it.
Since starting this investigation, I also refactored some of my singletons into @State/@ObservedObject dependencies. For example, my app root now wires up AuthManager, BackendService, and AccountManager (where API calls happen using async/await) as @State properties:
@State var authManager: AuthManager
@State var accountManager: AccountManager
@State var backendService: BackendService
init() {
let authManager = AuthManager()
self._authManager = .init(wrappedValue: authManager)
let backendService = BackendService(authManager: authManager)
self._backendService = .init(wrappedValue: backendService)
self._accountManager = .init(wrappedValue: AccountManager(backendService: backendService))
}
I don’t know if this refactor is related to the crash, but I am including it to be complete.
Apologies that I don’t have a minimized sample project — this issue seems app-wide, and all I have are the crash logs.
Request:
Given the crash location (URLConnectionLoader::loadWithWhatToDo), can Apple provide guidance on known scenarios or misuses that can lead to this crash?
Is there a way to get more actionable diagnostics from CFNetwork beyond CFNETWORK_DIAGNOSTICS to pinpoint whether it’s session lifetime, cached response corruption, or auth/redirect?
Can you also confirm whether my dependency setup above could contribute to URLSession or backend lifetime issues?
I can’t reliably reproduce the crash, and without Apple’s insight the stack trace is effectively opaque to me.
Thanks for your time and help. Happy to send multiple symbolicated crash logs at request.
Thanks for any help.
PS. Including 2 of many similar crash logs. Can provide more if needed.
Atlans-2025-07-29-154915_symbolicated (cfloader).txt
Atlans-2025-08-08-124226_symbolicated (cfloader).txt
I've been struggling with this issue since the release of macOS 15 Sequoia. I'm wondering if anyone else has encountered it or if anyone has a workaround to fix it.
Inserting a new element into the array that acts as data source for a SwiftUI List with a ForEach is never animated even if the insertion is wrapped in a withAnimation() call.
It seems that some other changes can be automated though: e.g. calls to shuffle() on the array successfully animate the changes.
This used to work fine on macOS 14, but stopped working on macOS 15.
I created a very simple project to reproduce the issue:
import SwiftUI
@main
struct TestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct IdentifiableItem: Identifiable {
let id = UUID()
var name: String { "Item \(id)" }
}
struct ContentView: View {
@State var items: [IdentifiableItem] = [
IdentifiableItem(), IdentifiableItem(), IdentifiableItem(), IdentifiableItem(), IdentifiableItem(),
IdentifiableItem(), IdentifiableItem(), IdentifiableItem(), IdentifiableItem(), IdentifiableItem(),
]
var body: some View {
List {
ForEach(items) { item in
Text(item.name)
}
}
Button("Add Item") {
withAnimation {
items.insert(IdentifiableItem(), at: 0)
}
}
Button("Shuffle Items") {
withAnimation {
items.shuffle()
}
}
}
}
How to reproduce
Copy the code below in an Xcode project.
Run it on macOS 15.
Hit the "Add Item" button
Expected: A new item is inserted with animation.
Result: A new item is inserted without animation.
How to prove this is a regression
Follow the same steps above but run on macOS 14.
A new item is inserted with animation.
How can I correctly display the cursor using a custom keyboard in SwiftUI without using UIKit? Currently, I'm encountering a conflict between the custom keyboard and the system keyboard in SwiftUI, resulting in both keyboards being displayed simultaneously. If I disable the system keyboard and then handle the custom keyboard, the cursor disappears. How can I resolve this issue?it?
What is the correct way to implement scrolling in a looong list that uses ScrollView and LazyVstack
Imagine I have some api that returns a longs list of comments with replies
The basic usecase is to scroll to the bottom(to the last comment) Most of the time this works fine
But, imagine some of the comments have many replies like 35 or more (or even 300)
User expands replies for the first post, then presses scroll to bottom.
The scrollbar reaches the bottom and I see the blank screen.
Sometimes the scrollbar may jump for a while before lazyvstack finishes loading or until I manually scroll up a bit or all the way up and down
What should I do in this case? Is this the swiftui performance problem that has no cure?
Abstract example:
ScrollViewReader { proxy in
ScrollView {
LazyVStack {
ForEach(comments) { comment in
CommentView(comment: comment)
.id("comment-\(comment.id)")
}
}
}
}
struct CommentView: View {
let comment: Comment
@State var isExpanded = false
var body: some View {
VStack {
Text(comment.text)
if isExpanded {
RepliesView(replies: comment.replies) // 35-300+ replies
}
}
}
}
...
scroll
proxy.scrollTo("comment-\(lastComment.id)", anchor: .bottom)
iOS simulator version 18.0+
I have a demo like this:
Menu {
Button {
} label: {
Text("Option 1")
Image(systemName: "star")
}
Button {
} label: {
Text("Option 2")
Image(systemName: "star")
}
} label: {
Text("Menu")
}
And I used the tool Accessibility Inspector to modify the text size.
Case 1:
We could see the option title and the star icon.
Case 2:
But we could not see the icon, only the option title here
Is this by design from Apple? Or does this need to be fixed? Does anyone know about my question?
I have a SwiftUI app. It fetches records through CoreData. And I want to show some records on a widget. I understand that I need to use AppGroup to share data between an app and its associated widget.
import Foundation
import CoreData
import CloudKit
class DataManager {
static let instance = DataManager()
let container: NSPersistentContainer
let context: NSManagedObjectContext
init() {
container = NSPersistentCloudKitContainer(name: "DataMama")
container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: group identifier)!.appendingPathComponent("Trash.sqlite"))]
container.loadPersistentStores(completionHandler: { (description, error) in
if let error = error as NSError? {
print("Unresolved error \(error), \(error.userInfo)")
}
})
context = container.viewContext
context.automaticallyMergesChangesFromParent = true
context.mergePolicy = NSMergePolicy(merge: .mergeByPropertyObjectTrumpMergePolicyType)
}
func save() {
do {
try container.viewContext.save()
print("Saved successfully")
} catch {
print("Error in saving data: \(error.localizedDescription)")
}
}
}
// ViewModel //
import Foundation
import CoreData
import WidgetKit
class ViewModel: ObservableObject {
let manager = DataManager()
@Published var records: [Little] = []
init() {
fetchRecords()
}
func fetchRecords() {
let request = NSFetchRequest<Little>(entityName: "Little")
do {
records = try manager.context.fetch(request)
records.sort { lhs, rhs in
lhs.trashDate! < rhs.trashDate!
}
} catch {
print("Fetch error for DataManager: \(error.localizedDescription)")
}
WidgetCenter.shared.reloadAllTimelines()
}
}
So I have a view model that fetches data for the app as shown above.
Now, my question is how should my widget get data from CoreData? Should the widget get data from CoreData through DataManager? I have read some questions here and also read some articles around the world. This article ( https://dev.classmethod.jp/articles/widget-coredate-introduction/ ) suggests that you let the Widget struct access CoreData through DataManager. If that's a correct fashion, how should the getTimeline function in the TimelineProvider struct get data? This question also suggests the same. Thank you for your reading my question.
I've run into a strange issue.
If a sheet loads a view that has a SwiftData @Query, and there is an if statement in the view body, I get the following error when running an iOS targetted SwiftUI app under MacOS 26.1:
Set a .modelContext in view's environment to use Query
While the view actually ends up loading the correct data, before it does, it ends up re-creating the sqlite store (opening as /dev/null).
The strange thing is that this only happens if there is an if statement in the body. The statement need not ever evaluate true, but it causes the issue.
Here's an example. It's based on the default xcode new iOS project w/ SwiftData:
struct ContentView: View {
@State private var isShowingSheet = false
var body: some View {
Button(action: { isShowingSheet.toggle() }) {
Text("Show Sheet")
}
.sheet(isPresented: $isShowingSheet, onDismiss: didDismiss) {
VStack {
ContentSheetView()
}
}
}
func didDismiss() { }
}
struct ContentSheetView: View {
@Environment(\.modelContext) private var modelContext
@Query public var items: [Item]
@State var fault: Bool = false
var body: some View {
VStack {
if fault { Text("Fault!") }
Button(action: addItem) {
Label("Add Item", systemImage: "plus")
}
List {
ForEach(items) { item in
Text(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))
}
}
}
}
private func addItem() {
withAnimation {
let newItem = Item(timestamp: Date())
modelContext.insert(newItem)
}
}
}
It requires some data to be added to trigger, but after adding it and dismissing the sheet, opening up the sheet with trigger the Set a .modelContext in view's environment to use Query. Flipping on -com.apple.CoreData.SQLDebug 1 will show it trying to recreate the database.
If you remove the if fault { Text("Fault!") } line, it goes away. It also doesn't appear to happen on iPhones or in the iPhone simulator.
Explicitly passing modelContext to the ContentSheetView like ContentSheetView().modelContext(modelContext) also seems to fix it.
Is this behavior expected?
Hello,
I'm having a problem with the .glasseffect modifier in a view of a SwiftUI application. I have a list that starts with a static element, followed by several dynamic entries, and then another static element. I've applied the .glasseffect modifier to all the elements, and it works fine except for the first static element. I think I've figured out what's causing it. This element contains two date pickers, and if I comment one out, it works. As soon as both are present, I get a BAD_ACCESS_ERROR.
Oddly enough, this only happens on the tablet. Everything runs normally in the simulator. If I remove the .glassmodifier and use a normal background, it still works.
Is this a bug, or is it against Liquid Glass to have two date pickers in a stack and then use the .glasseffect modifier?
I was trying to figure out why my bottom sheet looks weird and doesn't have the "proper glass" look. I found that this issue seems to be new to iOS 26.1.
See the images below, they show the same view hierarchy (in this case UIHostingController configured as bottom sheet that has NavigationStack and content.
On iOS 26.1 there seems to be extra two layers of background - even though I am no adding any.
iOS 26:
iOS 26.1
Has anyone experienced something similar? Any workarounds? I am happy to completely disable the glass effect for this bottom sheet if it helps.
The screenshots show one sheet, but the same thing happens for another ones.
Hi everyone,
I’m trying to reproduce the layout Apple Music uses for playlists, where there is header content above the table (artwork, title, buttons), and when you scroll, everything scrolls together—the header and table rows move as a single scrollable region.
Here’s an example of what I’m trying to achieve:
I’m using SwiftUI’s Table view and I haven’t found a clean way to place custom content above the table while keeping everything inside the same scroll view.
Is there currently a recommended way to achieve Apple Music–style scrollable header + table content using SwiftUI?
Thanks!
For information I stumbled upon a regression with SwiftUI Slider on iOS 26. Its onEditingChanged closure might be called twice when interaction ends, with a final Boolean incorrect value of true provided to the closure.
As a result apps cannot reliably rely on this closure to detect when an interaction with the slider starts or ends.
I filed a feedback under FB20283439 (iOS 26.0 regression: Slider onEditingChanged closure is unreliable).
Hello,
in my widget the user displays images filling the whole widget with overlayed texts (via ZStack). Via shadows or text background color the text gets better readable.
However, when a user chooses transparent or tinted colors for the home screen, the text is barely or not readable anymore since e.g. white text on white image background. How to resolve this issue?
Topic:
App & System Services
SubTopic:
Widgets & Live Activities
Tags:
SwiftUI
Visual Design
WidgetKit
Is anyone else experiencing NavigationStack title disappearing in iOS 26?
Hey everyone,
I just updated to iOS 26 and I'm running into a really frustrating issue with my app. Wondering if anyone else is seeing this or if I'm missing something obvious.
What's happening:
My navigation titles are completely blank when the app first loads, but then magically appear when I scroll down. It's super weird and makes my app look broken at first glance.
My setup:
I'm using NavigationStack with some pretty standard stuff:
Navigation title with .navigationTitle()
A toolbar with a settings button
ScrollView content with a gradient background
Here's basically what I have:
NavigationStack {
ScrollView {
VStack(spacing: 24) {
// My app content here - cards, etc.
ForEach(myItems) { item in
// Content cards
}
}
.padding()
}
.background(
LinearGradient(
gradient: Gradient(colors: [
Color.surfacePrimary,
Color.surfacePrimary.opacity(0.95),
Color.surfaceSecondary.opacity(0.3)
]),
startPoint: .top,
endPoint: .bottom
)
)
.navigationTitle("My Title") // ← This doesn't show up initially!
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("Settings") {
// Settings action
}
}
}
}
The weird part:
Works perfectly fine on my iOS 18.6.2 device
Completely broken on iOS 26 - blank navigation area
As soon as I scroll, the title appears and stays there
Happens on both simulator and physical device
What I've tried:
Double-checking my code (it's identical to what worked before)
Testing on multiple devices
Different navigation title strings
Removing and re-adding the toolbar
Has anyone else run into this? I'm thinking it might be an iOS 26 bug with NavigationStack, but I wanted to check if others are seeing it before filing a radar.
It's affecting my main landing screens (Tennis, NFL, and Prediction Markets tabs) and honestly looks pretty bad when users first open the app and see blank headers.
Temporary fix I found:
If anyone else hits this, I discovered that forcing inline titles works as a workaround:
.navigationTitle("My Title")
.navigationBarTitleDisplayMode(.inline) // This fixes it but kills large titles
Obviously not ideal since we lose the nice large title behavior, but at least the titles show up.
Questions:
Is this happening to anyone else's iOS 26 apps?
Any better workarounds that preserve large titles?
Should I file this as a radar or is Apple already aware?
Really hoping this gets fixed soon - having to choose between broken navigation or losing large titles is pretty frustrating.
Thanks for any insights!
Anyone else dealing with this NavigationStack nightmare in iOS 26? 😅
Our app was just rejected by Apple because they say the subscription management sheet never loads. It just spins indefinitely.
We're using StoreKit's manageSubscriptionsSheet view modifier to present the sheet, and it's always worked for us when testing in SandBox.
Has anyone else had this problem?
Given that it's Apple's own code that got us rejected, what's our path forward?
I understand this is a known issue, but it’s truly unacceptable that it remains unresolved. Allowing users to customize toolbars is a fundamental macOS feature, and it has been broken since the release of macOS 15.
How is it possible that this issue persists even in macOS 15.3 beta (24D5040f)?
FB15513599
import SwiftUI
struct ContentView: View {
@State private var showEditItem = false
var body: some View {
VStack {
VStack {
Text("Instructions to reproduce the crash")
.font(.title)
.padding()
Text("""
1. Click on "Toggle Item"
2. In the menu go to File > New Window
3. In new window, click on "Toggle Item"
""")
}
.padding()
Button {
showEditItem.toggle()
} label: {
Text("Toggle Item")
}
}
.padding()
.toolbar(id: "main") {
ToolbarItem(id: "new") {
Button {
} label: {
Text("New…")
}
}
if showEditItem {
ToolbarItem(id: "edit") {
Button {
} label: {
Text("Edit…")
}
}
}
}
}
}
[Also submitted as FB20225387]
When using a custom SF Symbol that combines a base symbol with a badge, the symbol doesn’t stay vertically centered when displayed in code. The vertical alignment shifts based on the Y offset of the badge.
There are two problems with this:
The base element shouldn’t move vertically when a badge is added—the badge is meant to add to the symbol, not change its alignment.
The badge position should be consistent with system-provided badged symbols, where badges always appear in a predictable spot relative to the corner they're in (usually at X,Y offsets of 90% or 10%).
Neither of these behaviors match what’s expected, leading to inconsistent and misaligned symbols in the UI.
Screenshot of Problem
The ellipsis shifts vertically whenever the badge Y offset is set to anything other than 50%. Even at a 90/10 offset, it still doesn’t align with the badge position of the system "envelope.badge" symbol.
SF Symbols Export
This seem to be a SwiftUI issue since both the export from SF Symbols is correctly centered:
Xcode Assets Preview
And it's also correct in the Xcode Assets preview:
Steps to Repro
In SF Symbols, create a custom symbol of "ellipsis" (right-click and Duplicate as Custom Symbol)
Combine it with the "badge" component (select Custom Symbols, select the newly-created "custom.ellipsis", then right-click and Combine Symbol with Component…)
Change the badge's Y Offset to 10%.
Export the symbol and add it to your Xcode asset catalog.
In Xcode, display the symbol inside a Button using Image(“custom.ellipsis.badge”).
Add a couple more buttons separated by spacers, using system images of "ellipsis" and "app.badge".
Compare the "custom.ellipsis.badge" button to the two system symbol buttons.
Expected
The combined symbol remains vertically centered, matching the alignment shown in both the SF Symbols export window and the Xcode asset catalog thumbnails.
Actual
The base symbol (e.g., the ellipsis portion) shifts vertically based on the Y offset of the badge element. This causes visual misalignment when displayed in SwiftUI toolbars or other layouts. Also included the system “envelope.badge” icon to show where a 90%, 10% badge offset should be located.
System Info
SF Symbols Version 7.0 (114)
Xcode Version 26.0 (17A321)
macOS 15.6.1 (24G90)
iOS 26.0 (23A340)