I'm trying to render a markdown with a link using Text.
If the URL of the link is a static string, then no problem. If the URL is a property, then OpenURLAction gets a string ‘%25@’. I think this may be a bug.
struct ContentView: View {
let url = "https://www.google.com"
var body: some View {
Text("[Terms of Service](\(url))")
.environment(\.openURL, OpenURLAction(handler: { url in
print(url)
return .handled
}))
}
}
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
I'm developing the VisionOS app. I want to know how to play spatial audio in addition to RealityKit? If it's iOS or macOS, how to play spatial audio in addition to RealityKit?
Pasting either plain or styled text into any TextEditor results in a memory leak.
import SwiftUI
struct EditorView: View {
@State private var inputText: String = ""
var body: some View {
VStack{
TextEditor(text: $inputText)
.frame(minHeight: 150)
}
}
}
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
Button ("Button 1") {
print ("Button 1");
}
.keyboardShortcut("k", modifiers: .command)
Button ("Button 2") {
print ("Button 2");
}
.keyboardShortcut("k", modifiers: .command)
}
}
}
I the above snippet, I have assigned the same keyboard shortcut (cmd +k) to 2 different buttons. According to the docs, if multiple controls are associated with the same shortcut, the first one found is used.
How do I figure out if Button 1 would be found first during the traversal or Button 2 ?
Is it based on the order of declaration? Is it always the case that Button 1 would be found first since it was declared before Button 2 ?
In Vision OS app, We have two types of windows:
Main App Window – This is the default window that launches when the app starts. It displays the video listings and other primary content.
Immersive Space Window – This opens only when a user starts streaming or playing a video.
Issue:
When entering the immersive space, the main app window remains visible in front of it unless manually closed. To avoid this, I currently close the main window when transitioning to immersive space and reopen it when exiting. However, this causes the app to restart instead of resuming from its previous state.
Desired Behavior:
I want the main app window to retain its state and seamlessly resume from where it was before entering immersive mode, rather than restarting.
Attempts & Challenges:
Tried managing opacity, visibility, and state preservation, but none worked as expected.
Couldn’t find a way to push the main window to the background while bringing the immersive space to the foreground.
Looking for a solution to keep the main window’s state intact while transitioning between immersive and normal modes.
With the introduction of the new matchedTransitionSource from iOS 18, we can apply a zoom transition in the navigation view using .navigationTransition(.zoom) This works well for zoom animations.
However, when I try to apply a matched geometry effect to views that are similar in the source and destination views, the zoom transition works, but those views don't transition seamlessly as they do with a matched geometry effect.
Is it possible to still use matched geometry for subviews of the source and destination views along with the new navigationTransition?
Here’s a little demo that reproduces this behaviour:
struct ContentView: View {
let colors: [[Color]] = [
[.red, .blue, .green],
[.yellow, .purple, .brown],
[.cyan, .gray]
]
@Namespace() var namespace
var body: some View {
NavigationStack {
Grid(horizontalSpacing: 50, verticalSpacing: 50) {
ForEach(colors, id: \.hashValue) { rowColors in
GridRow {
ForEach(rowColors, id: \.self) { color in
NavigationLink {
DetailView(color: color, namespace: namespace)
.navigationTransition(
.zoom(
sourceID: color,
in: namespace
)
)
.edgesIgnoringSafeArea(.all)
} label: {
ZStack {
RoundedRectangle(cornerRadius: 5)
.foregroundStyle(color)
.frame(width: 48, height: 48)
Image(systemName: "star.fill")
.foregroundStyle(Material.bar)
.matchedGeometryEffect(id: color,
in: namespace,
properties: .frame, isSource: false)
}
}
.matchedTransitionSource(id: color, in: namespace)
}
}
}
}
}
}
}
struct DetailView: View {
var color: Color
let namespace: Namespace.ID
var body: some View {
ZStack {
color
Image(systemName: "star.fill")
.resizable()
.foregroundStyle(Material.bar)
.matchedGeometryEffect(id: color,
in: namespace,
properties: .frame, isSource: false)
.frame(width: 100, height: 100)
}
.navigationBarHidden(false)
}
}
#Preview {
ContentView()
}
The save credentials prompt is not shown after clicking the submit button in the following setup. The prompt is shown if I move the email field before the login field.
Is it really required to have login and password fields at the end of the registration form? Or is there some API that can trigger the prompt?
struct FakeRegistrationView: View {
@State private var login = ""
@State private var password = ""
@State private var repeatPassword = ""
@State private var email = ""
var navigateBack: () -> Void
var body: some View {
VStack(spacing: 16) {
TextField("Login", text: $login)
.textFieldStyle(.roundedBorder)
.textContentType(.username)
.disableAutocorrection(true)
.autocapitalization(.none)
.frame(maxWidth: 300)
SecureField("Password", text: $password)
.textFieldStyle(.roundedBorder)
.textContentType(.newPassword)
.disableAutocorrection(true)
.autocapitalization(.none)
.frame(maxWidth: 300)
SecureField("Repeat password", text: $repeatPassword)
.textFieldStyle(.roundedBorder)
.textContentType(.newPassword)
.disableAutocorrection(true)
.autocapitalization(.none)
.frame(maxWidth: 300)
TextField("Email", text: $email)
.textFieldStyle(.roundedBorder)
.textContentType(.emailAddress)
.disableAutocorrection(true)
.autocapitalization(.none)
.frame(maxWidth: 300)
Button {
Task {
try? await Task.sleep(for: .seconds(2))
navigateBack()
}
} label: {
Text("Submit")
}
.buttonStyle(.borderedProminent)
}
}
}
I am trying to build a text editor that shrinks to its content size. The closest I have been able to get has been to add the .scrollDisabled(true) and .fixedSize(horizontal: false, vertical: true) modifiers.
This almost achieves what I need. There are two problems though:
long single line text gets cut off at the end
creating line breaks causes the text editor to grow vertically as expected (uncovering the cut off text in point 1 above). However, when you delete the line breaks, the TextEditor does not shrink again.
I have had a radar open for some time: FB13292506. Hopefully opening a thread here will get more visibility.
And here is some sample code to easily reproduce the issue:
import SwiftUI
struct ContentView: View {
@State var text = "[This is some long text that will be cut off at the end of the text editor]"
var body: some View {
TextEditor(text: $text)
.scrollDisabled(true)
.fixedSize(horizontal: false, vertical: true)
}
}
#Preview {
ContentView()
}
Here is a gif of the behavior:
I’m so lost on this. I’ve tried Google, ChatGPT, DeepSeek, the documentation. I’ve spent about 7 hours on this specific bug. Not sure what to do next. Does anyone have an idea?
I've been thinking a lot about how navigation and presentation are managed in SwiftUI, and I wanted to propose an idea for a more streamlined approach using environment values. Right now, handling navigation can feel fragmented — especially when juggling default NavigationStack, modals, and tab selections.
What if SwiftUI provided a set of convenience environment values for these common actions?
Tabs
@Environment(\.selectedTab) var selectedTab
@Environment(\.selectTab) var selectTab
selectedTab: Read the current tab index
selectTab(index: Int): Programmatically switch tabs
Stack Navigation
@Environment(\.stackCount) var stackCount
@Environment(\.push) var push
@Environment(\.pop) var pop
@Environment(\.popToRoot) var popToRoot
stackCount: Read how many views are in the navigation stack
push(destination: View): Push a new view onto the stack
pop(last: Int = 1): Pop the last views
popToRoot(): Return to the root view
Modals
@Environment(\.sheet) var sheet
@Environment(\.fullScreenCover) var fullScreenCover
@Environment(\.popover) var popover
@Environment(\.dismissModal) var dismissModal
sheet(view: View): Present a sheet
fullScreenCover(view: View): Present a full-screen cover
popover(view: View): Show a popover
dismissModal(): Dismiss any presented modal
Alerts & Dialogs
@Environment(\.alert) var alert
@Environment(\.confirmationDialog) var confirmationDialog
@Environment(\.openAppSettings) var openAppSettings
alert(title: String, message: String): Show an alert
confirmationDialog(title: String, actions: [Button]): Show a confirmation dialog
openAppSettings(): Directly open the app’s settings
Why?
Clean syntax: This keeps navigation code clean and centralized.
Consistency: Environment values already manage other app-level concerns (color scheme, locale, etc.). Why not navigation too?
Reusability: This approach is easy to adapt across different view hierarchies.
Example
@main
struct App: App {
var body: some Scene {
WindowGroup {
TabView {
NavigationStack {
ProductList()
}
.tabItem { ... }
NavigationStack {
OrderList()
}
.tabItem { ... }
}
}
}
}
struct ProductList: View {
@Environment(\.push) var push
@State var products: [Product] = []
var body: some View {
List(protucts) { product in
Button {
push(destination: ProductDetails(product: product))
}
} label: {
...
}
}
.task { ... }
}
}
struct ProductDetails: View { ... }
When trying to debug a mysterious app crash pointing to some layoutIfNeeded() method call, me and my QA team member reduced it to this sample app.
struct ContentView: View {
@State var isPresented = false
var body: some View {
VStack {
Button {
isPresented = true
} label: {
Text("show popover")
}
.popover(isPresented: $isPresented) {
Text("hello world")
}
}
.padding()
}
}`
This code crashes on his iPad iOS 18.1.0 22B5034E with EXC_BAD_ACCESS error. It is not reproducible on simulator or on device with iOS 18.2 or iOS 17.
Is this a known issue? Are there any known workarounds? I've found similar posts here
https://developer.apple.com/forums/thread/769757
https://developer.apple.com/forums/thread/768544
But they are about more specific cases.
I want to get to a point where I can use a small view with a query for my SwiftData model like this:
@Query
private var currentTrainingCycle: [TrainingCycle]
init(/*currentDate: Date*/) {
_currentTrainingCycle = Query(filter: #Predicate<TrainingCycle> {
$0.numberOfDays > 0
// $0.startDate < currentDate && currentDate < $0.endDate
}, sort: \.startDate)
}
The commented code is where I want to go. In this instance, it'd be created as a lazy var in a viewModel to have it stable (and not constantly re-creating the view). Since it was not working, I thought I could check the same view with a query that does not require any dynamic input. In this case, the numberOfDays never changes after instantiation.
But still, each time the app tries to create this view, the app becomes unresponsive, the CPU usage goes at 196%, memory goes way high and the device heats up quickly.
Am I holding it wrong? How can I have a dynamic predicate on a View in SwiftUI with SwiftData?
The issue I'm facing arise when using a lazyvstack within a navigationstack. I want to use the pinnedViews: .sectionHeaders feature from the lazyStack to display a section header while rendering the content with a scrollview. Below is the code i'm using and at the end I share a sample of the loop issue:
struct SProjectsScreen: View {
@Bindable var store: StoreOf<ProjectsFeature>
@State private var searchText: String = ""
@Binding var isBotTabBarHidden: Bool
@Environment(\.safeArea) private var safeArea: EdgeInsets
@Environment(\.screenSize) private var screenSize: CGSize
@Environment(\.dismiss) var dismiss
private var isLoading : Bool {
store.projects.isEmpty
}
var body: some View {
NavigationStack(path:$store.navigationPath.sending(\.setNavigationPath)) {
ScrollView(.vertical){
LazyVStack(spacing:16,pinnedViews: .sectionHeaders) {
Section {
VStack(spacing:16) {
if isLoading {
ForEach(0..<5,id:\.self) { _ in
ProjectItemSkeleton()
}
}
else{
ForEach(store.projects,id:\._id) { projectItem in
NavigationLink(value: projectItem) {
SProjectItem(project: projectItem)
.foregroundStyle(Color.theme.foreground)
}
.simultaneousGesture(TapGesture().onEnded({ _ in
store.send(.setCurrentProjectSelected(projectItem.name))
}))
}
}
}
} header: {
VStack(spacing:16) {
HStack {
Text("Your")
Text("Projects")
.fontWeight(.bold)
Text("Are Here!")
}
.font(.title)
.frame(maxWidth: .infinity,alignment: .leading)
.padding(.horizontal,12)
.padding(.vertical,0)
HStack {
SSearchField(searchValue: $searchText)
Button {
} label: {
Image(systemName: "slider.horizontal.3")
.foregroundStyle(.white)
.fontWeight(.medium)
.font(.system(size: 24))
.frame(width:50.66,height: 50.66)
.background {
Circle().fill(Color.theme.primary)
}
}
}
}
.padding(.top,8)
.padding(.bottom,16)
.background(content: {
Color.white
})
}
}
}
.scrollIndicators(.hidden)
.navigationDestination(for: Project.self) { project in
SFoldersScreen(project:project,isBotTabBarHidden: $isBotTabBarHidden)
.toolbar(.hidden)
}
.padding(.horizontal,SScreenSize.hPadding)
.onAppear {
Task {
if isLoading{
do {
let projectsData = try await ProjectService.Shared.getProjects()
store.send(.setProjects(projectsData))
}
catch{
print("error found: ",error.localizedDescription)
}
}
}
}
.refreshable {
do {
let projectsData = try await ProjectService.Shared.getProjects()
store.send(.setProjects(projectsData))
}
catch{
print("error found: ",error.localizedDescription)
}
}
}.onChange(of: store.navigationPath, { a, b in
print("Navigation path changed:", b)
})
}
}
I'm using tca library for managing states so this is my project feature reducer:
import ComposableArchitecture
@Reducer
struct ProjectsFeature{
@ObservableState
struct State: Equatable{
var navigationPath : [Project] = []
var projects : [Project] = [
]
var currentProjectSelected : String?
}
enum Action{
case setNavigationPath([Project])
case setProjects([Project])
case setCurrentProjectSelected(String?)
case popNavigation
}
var body: some ReducerOf<Self> {
Reduce { state, action in
switch action {
case .setNavigationPath(let navigationPath):
state.navigationPath = navigationPath
return .none
case .setProjects(let projects):
state.projects = projects
return .none
case .setCurrentProjectSelected(let projectName):
state.currentProjectSelected = projectName
return .none
case .popNavigation:
if !state.navigationPath.isEmpty {
state.navigationPath.removeLast()
}
state.currentProjectSelected = nil
return .none
}
}
}
I want to show a view, where the user can add or remove items shown as icons, which are sorted in two groups: squares and circles.
When there are only squares, they should be shown in one row:
[] [] []
When there are so many squares that they don’t fit horizontally, a (horizontal) scrollview will be used, with scroll-indicator always shown to indicate that not all squares are visible.
When there are only circles, they also should be shown in one row:
() () ()
When there are so many circles that they don’t fit horizontally, a (horizontal) scrollview will be used, with scroll-indicator always shown to indicate that not all circles are visible.
When there a few squares and a few circles, they should be shown adjacent in one row:
[] [] () ()
When there are so many squares and circles that they don’t fit horizontally, they should be shown in two rows, squares on top, circles below:
[] [] []
() () ()
When there are either too many squares or too many circles (or both) to fit horizontally, one common (horizontal) scrollview will be used, with scroll-indicator always shown to indicate that not all items are visible.
I started with ViewThatFits: (see first code block)
{
let squares = HStack {
ForEach(model.squares, id: \.self) { square in
Image(square)
}
}
let circles = HStack {
ForEach(model.circles, id: \.self) { circle in
Image(circle)
}
}
let oneLine = HStack {
squares
circles
}
let twoLines = VStack {
squares
circles
}
let scrollView = ScrollView(.horizontal) {
twoLines
}.scrollIndicators(.visible)
ViewThatFits(in: .horizontal) {
oneLine
twoLines
scrollView.clipped()
}
}
While this works in general, it doesn’t animate properly.
When the user adds or removes an image the model gets updated, (see second code block)
withAnimation(Animation.easeIn(duration: 0.25)) {
model.squares += image
}
and the view animates with the existing images either making space for a new appearing square/circle, or moving together to close the gap where an image disappeared.
This works fine as long as ViewThatFits returns the same view.
However, when adding 1 image leads to ViewThatFits switching from oneLine to twoLines, this switch is not animated. The circles jump to the new position under the squares, instead of sliding there.
I searched online for a solution, but this seems to be a known problem of ViewThatFits. It doesn't animate when it switches...
(tbc)
UIKit and SwiftUI each have their own strengths and weaknesses:
UIKit: More performant (e.g., UICollectionView).
SwiftUI: Easier to create shiny UI and animations.
My usual approach is to base my project on UIKit and use UIHostingController whenever I need to showcase visually rich UI or animations (such as in an onboarding presentation).
So far, this approach has worked well for me—it keeps the project clean while solving performance concerns effectively.
However, I was wondering: Has anyone tried the opposite approach?
Creating a project primarily in SwiftUI, then embedding UIKit when performance is critical.
If so, what has your experience been like? Would you recommend this approach?
I'm considering this for my next project but am unsure how well it would work in practice.
Simple master screen with list, NavigationLink to editable detail view.
I want edits on the detail screen to update to the master list "cars" variable and the list UI.
On the detail view, if I edit one field and exit the field, the value reverts to the original value. Why?
If I edit one field, don't change focus and hit the back button. The master list updates. This is what I want, but I can only update 1 field because of problem #1. Should be able to edit all the fields.
If I implement the == func in the Car struct, then no updates get saved. Why?
struct Car: Hashable, Equatable {
var id: UUID = UUID()
var make: String
var model: String
var year: Int
// static func == (lhs: Car, rhs: Car) -> Bool {
// return lhs.id == rhs.id
// }
}
struct ContentView: View {
@State private var cars: [Car]
init() {
cars = [
Car(make: "Toyota", model: "Camry", year: 2020),
Car(make: "Honda", model: "Civic", year: 2021),
Car(make: "Ford", model: "Mustang", year: 2022),
Car(make: "Chevrolet", model: "Malibu", year: 2023),
Car(make: "Nissan", model: "Altima", year: 2024),
Car(make: "Kia", model: "Soul", year: 2025),
Car(make: "Volkswagen", model: "Jetta", year: 2026)
]
}
var body: some View {
NavigationStack {
VStack {
ForEach($cars, id: \.self) { $car in
NavigationLink(destination: CarDetailView(car: $car)){
Text(car.make)
}
}
}
}
}
}
struct CarDetailView: View {
@Binding var car: Car
var body: some View {
Form {
TextField("Make", text: $car.make)
TextField("Model", text: $car.model)
TextField("Year", value: $car.year, format: .number)
}
}
}
How do I filter data using @Query with a Set of DateComponents? I successfully saved multiple dates using a MultiDatePicker in AddView.swift. In ListView.swift, I want to retrieve all records for the current or today’s date.
There are hundreds of examples using @Query with strings and dates, but I haven’t found an example of @Query using a Set of DateComponents
Nothing will compile and after hundreds and hundreds of attempts, my hair is turning gray.
Please, please, please help me.
For example, if the current date is Tuesday, March 4 205, then I want to retrieve both records. Since both records contain Tuesday, March 4, then retrieve both records. Sorting works fine because the order by clause uses period which is a Double.
Unfortunately, my syntax is incorrect and I don’t know the correct predicate syntax for @Query and a Set of DateComponents.
Class Planner.swift file
import SwiftUI
import SwiftData
@Model
class Planner {
//var id: UUID = UUID()
var grade: Double = 4.0
var kumi: Double = 4.0
var period: Double = 1.0
var dates: Set<DateComponents> = []
init(
grade: Double = 4.0, kumi: Double = 4.0, period: Double = 1.0, dates: Set<DateComponents> = []
)
{
self.grade = grade
self.kumi = kumi
self.period = period
self.dates = dates
}
}
@Query Model snippet of code does not work
The compile error is to use a Set of DateComponents, not just DateComponents.
@Query(filter: #Predicate<Planner> { $0.dates = DateComponents(calendar: Calendar.current, year: 2025, month: 3, day: 4)},
sort: [SortDescriptor(\Planner.period)])
var planner: [Planner]
ListView.swift image
EditView.swift for record #1
DB Browser for SQLlite: record #1 (March 6, 2025 and March 4, 2025)
[{"isLeapMonth":false,"year":2025,"day":6,"month":3,"calendar":{"identifier":"gregorian","minimumDaysInFirstWeek":1,"current":1,"locale":{"identifier":"en_JP","current":1},"firstWeekday":1,"timeZone":{"identifier":"Asia\/Tokyo"}},"era":1},{"month":3,"year":2025,"day":4,"isLeapMonth":false,"era":1,"calendar":{"locale":{"identifier":"en_JP","current":1},"timeZone":{"identifier":"Asia\/Tokyo"},"current":1,"identifier":"gregorian","firstWeekday":1,"minimumDaysInFirstWeek":1}}]
EditView.swift for record #2
DB Browser for SQLlite: record #2 (March 3, 2025 and March 4, 2025)
[{"calendar":{"minimumDaysInFirstWeek":1,"locale":{"current":1,"identifier":"en_JP"},"timeZone":{"identifier":"Asia\/Tokyo"},"firstWeekday":1,"current":1,"identifier":"gregorian"},"month":3,"day":3,"isLeapMonth":false,"year":2025,"era":1},{"year":2025,"month":3,"era":1,"day":4,"isLeapMonth":false,"calendar":{"identifier":"gregorian","current":1,"firstWeekday":1,"minimumDaysInFirstWeek":1,"timeZone":{"identifier":"Asia\/Tokyo"},"locale":{"current":1,"identifier":"en_JP"}}}]
Any help is greatly appreciated.
In my app, I have a ShareLink that attempts to share a movie.
struct MovieTransferable: Transferable {
let url: URL
let writeMovie: (URL) -> ()
static var transferRepresentation: some TransferRepresentation {
DataRepresentation(
exportedContentType: .movie,
exporting: {
(movie) in
// Write the movie into documents.
movie.writeMovie(movie.url)
return try! Data(contentsOf: movie.url)
})
FileRepresentation(
exportedContentType: .movie,
exporting: {
(movie) in
// Write the movie into documents.
movie.writeMovie(movie.url)
return SentTransferredFile(movie.url)
})
}
}
The ShareLink works if you try to share the movie with the Photos app, Air Drop, and iMessage. If I share to WhatsApp, the movie shows up as empty (zero length), but there's a movie. If I share to Discord, the movie is not displayed at all (only the comment). Instagram posts a dialog saying it won't allow movies and to use the app (why are they even in the ShareLink option for movies?). YouTube processes for a bit and then does nothing (no upload).
Are there things that I can do to make the Transferable accepted at more of the end points? It's at fps 30 and I've tried most of the available codec's. The size is the same as the iPhone's screen, so the aspect ratio is a bit odd. However, if I go directly to the app (Discord, etc...) upload from my phone works fine.
Any help would be appreciated to make this more viable.
Hello Apple Developer Community,
I’m facing a recurring issue in my SwiftUI iOS app where a specific view fails to reload correctly after saving edits and navigating back to it. The failure happens consistently post-save, and I’m looking for insights from the community.
🛠 App Overview
Purpose
A SwiftUI app that manages user-created data, including images, text fields, and completion tracking.
Tech Stack:
SwiftUI, Swift 5.x
MSAL for authentication
Azure Cosmos DB (NoSQL) for backend data
Azure Blob Storage for images
Environment:
Xcode 15.x
iOS 17 (tested on iOS 18.2 simulator and iPhone 16 Pro)
User Context:
Users authenticate via MSAL.
Data is fetched via Azure Functions, stored in Cosmos DB, and displayed dynamically.
🚨 Issue Description
🔁 Steps to Reproduce
Open a SwiftUI view (e.g., a dashboard displaying a user’s saved data).
Edit an item (e.g., update a name, upload a new image, modify completion progress).
Save changes via an API call (sendDataToBackend).
The view navigates back, but the image URL loses its SAS token.
Navigate away (e.g., back to the home screen or another tab).
Return to the view.
❌ Result
The view crashes, displays blank, or fails to load updated data.
SwiftUI refreshes text-based data correctly, but AsyncImage does not.
Printing the image URL post-save shows that the SAS token (?sv=...) is missing.
❓ Question
How can I properly reload AsyncImage after saving, without losing the SAS token?
🛠 What I’ve Tried
✅ Verified JSON Structure
Debugged pre- and post-save JSON.
Confirmed field names match the Codable model.
✅ Forced SwiftUI to Refresh
Tried .id(UUID()) on NavigationStack:
NavigationStack {
ProjectDashboardView()
.id(UUID()) // Forces reinit
}
Still fails intermittently.
✅ Forced AsyncImage to Reload
Tried appending a UUID() to the image URL:
AsyncImage(url: URL(string: "\(imageUrl)?cacheBust=\(UUID().uuidString)"))
Still fails when URL query parameters (?sv=...) are trimmed.
I’d greatly appreciate any insights, code snippets, or debugging suggestions! Let me know if more logs or sample code would help.
Thanks in advance!
I can't get my app's logo to show in the "About" box nor in the app switcher.
I have:
created "Assets.xcassets"
created "AppIcon"
added 10 image files of the logo to the AppIcon image well [? right terminology ?]
saved and built the project – there are no errors or warnings
When I run the project, I still get the default image showing in the About box and in the app switcher.
Because first attempt failed, I changed "applet" to "AppIcon" in "App Icons and Launch Screen" in "General" settings. That did not change the result. I also toggled "Include all app icon assets" which also did not change the result.
Weirdly, my app's logo DOES show beside the app name in every item of "Build Settings".
Do I need to do something else to change the default image in the "About" box ?
Thanks.
[Xcode 16.2 on macOS 15.3.2.]