I’m building a document-based SwiftData app (iPhone/iPad/Mac). Here’s a minimal example of how I’m using DocumentGroup.
DocumentGroup(editing: Trip.self, contentType: .trips) {
ContentView()
}
if #available(iOS 18.0, *) {
DocumentGroupLaunchScene {
NewDocumentButton("New Trip")
}
}
I’m struggling with the toolbar behavior in DocumentGroup apps. My content view uses a TabView, and each tab contains a NavigationSplitView. After I select a document in the document browser, I see my tabs. Regardless of which tab is selected, there’s a navigation bar showing the document name and a back button to the document browser. However, only the first tab shows the disclosure button to rename the document. I’d expect to be able to rename the document anywhere the name is shown.
When I navigate to the detail view of my NavigationSplitView (or when using NavigationView/NavigationStack), I still see that back button to the document browser. When the user taps it, they expect to go back to the previous view, not to the document browser.
What’s really odd is that even sheet or fullScreenCover presentations include these document UI elements in the navigation bar. I can’t get rid of them. Even if I set a title via the toolbar or navigationTitle, the rename disclosure button remains visible.
Do DocumentGroup apps intentionally show their specific navigation bar everywhere? Is this a bug or expected behavior? And is it expected that the rename disclosure button appears only on the first tab of a TabView?
SwiftUI
RSS for tagProvide views, controls, and layout structures for declaring your app's user interface using SwiftUI.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Hi everyone!
I've noticed a color rendering issue with Home Screen widgets on iOS 26: the colors displayed in widgets are inconsistent with those shown inside the app. At first, I suspected this might be caused by differences in color spaces, but even after explicitly specifying the color space for SwiftUI.Color or UIColor, the widget colors remain incorrect.
Steps to reproduce:
Create a new iOS project in Xcode 26 beta 6.
Add a new Widget Extension target.
Use the following Widget view code:
struct MyWidgets: Widget {
let kind: String = "MyWidgets"
var body: some WidgetConfiguration {
StaticConfiguration(kind: kind, provider: Provider()) { entry in
let white = Color(.sRGB, red: 1, green: 1, blue: 1)
let veryLightGray = Color(.sRGB, red: 0.96, green: 0.96, blue: 0.96)
let lightGray = Color(.sRGB, red: 0.9, green: 0.9, blue: 0.9)
VStack(spacing: 0) {
Rectangle()
.foregroundStyle(veryLightGray) // 👈
Rectangle()
.foregroundStyle(lightGray) // 👈
}
.containerBackground(white, for: .widget) // 👈
}
.configurationDisplayName("My Widget")
}
}
⬆️ In-app, the colors are correct: the top block is a very light gray (white=0.96)✅, and the bottom block is a regular gray (white=0.90)✅.
However, on the Home Screen widget, the result is as follows:
⬆️ The top light gray block blends completely into the white background and is indistinguishable; the bottom gray block also appears lighter than it does in-app ❌. This issue occurs both on the simulator and on real devices. (Interestingly, the colors are correct in the Xcode Preview.)
Whether I declare colors in code (SwiftUI.Color or UIColor) or in the Asset Catalog, the widget's color rendering does not match expectations.
What's even stranger is that if I add an extra pure white block (white=1.0) to the view, it immediately affects all the colors in the widget:
This whole behavior makes it very difficult to set accurate colors for widgets on iOS 26. While it seems related to glass effect rendering and color space handling, I still feel there might be a bug in the implementation.
When using NSTableView or NSOutlineView, if you use an NSTableCellView and wire up the .imageView and .textField properties then you get some "free" behaviour with respect to styling and sizing of those fields. (ex: They reflect the user's preferred "Sidebar Icon Size" as selected in Settings. )
If I'm using a SwiftUI View inside an NSTableCellView, is there any way to connect a Text or Image to those properties?
Consider the following pseudo code:
struct MyCellView: View {
let text: String
let url: URL?
var body: some View {
HStack {
Image(...) // How to indicate this is .imageView?
Text(...) // How to indicate this is .textField?
}
}
}
final class MyTableCellView: NSTableCellView {
private var hostingView: NSHostingView<MyCellView>!
init() {
self.hostingView = NSHostingView(rootView: MyCellView(text: "", url: nil))
self.addSubview(self.hostingView)
}
func configureWith(text: String, url: URL) {
let rootView = MyCellView(text: text, url: url)
hostingView.rootView = rootView
// How can I make this connection?
self.textField = rootView.???
self.imageView = rootView.???
}
}
I'm ideally looking for a solution that works on macOS 15+.
Hi,
I’m working with CPGridTemplate in CarPlay. According to the documentation, it supports up to 9 CPGridButton objects and should display them in a grid (up to 3×3).
However, I’ve run into two issues:
Row instead of grid
When I add 4–6 buttons, they don’t appear in a 2×2 or 2×3 grid. Instead, they are shown in a single
horizontal row. Even 9 buttons do not appear in a 3x3 grid.
More than 9 buttons
My use case requires more than 9 icons, but it looks like CPGridTemplate ignores any additional buttons beyond the first 9. Is there any supported way to display more than 9 buttons in a grid, or is pagination/multiple templates the only option?
Thanks in advance!
Navigation Title no longer showing for first Tab in iOS/iPadOS 26 (Directives) in my app Starship SE Corps when running is Xcode 26 simulator and on iPad device itself running iPadOS 26 beta.
Launch app
Notice Navigation Title “Directives” is missing from top tab in Sidebar and Floating Tab View (iPad) and TabView (iOS).
Navigate to other tabs and Navigation Titles appear as expected.
Worked fine (as expected) in iOS/iPadOS 18.5, but broken in iOS/iPadOS 26.
Reference Feedback: FB17987650
Hi,
In the Apple Scrumdinger sample, the SpeechRecognizer class conforms to the Observable protocol:
public actor SpeechRecognizer: Observable {
public enum RecognizerError: Error {
case nilRecognizer
.
.
.
The developer help text suggests that the protocol conformance does not add observation functionality.
This class does not use the @Observable macro.
So, how does this work under the hood?
When using a custom button style to generate the button label, it will be clipped.
You can check below sample, the first one is render fine, but the second button with custom style will be clipped.
struct ContentView: View {
var body: some View {
NavigationStack {
List {}
.toolbar {
ToolbarItem(placement: .topBarLeading) {
Button {
} label: {
HStack {
Image(systemName: "chevron.backward")
Text("Back")
}
}
}
ToolbarItem(placement: .topBarLeading) {
Button {
} label: {
EmptyView()
}
.buttonStyle(MyButtonStyle())
}
}
.navigationTitle("Title")
}
}
}
struct MyButtonStyle: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
HStack {
Image(systemName: "chevron.backward")
Text("Back")
}
}
}
Topic:
UI Frameworks
SubTopic:
SwiftUI
After a lot of testing and diagnosing, I found that when going to a item creation page, creating an item, navigating back to a TabView with a tabViewStyle of PageTabViewStyle and a navigationTitle that is displaying that data, and all inside of a NavigationStack, the app hangs. I have tested this on iOS 18.2, on both a simulator and a physical iPhone 16 Pro Max, and it always hangs, not crashing. However, when run on My Mac (Designed for iPad) and the iPad simulator, it doesn't crash.
This could just be a really niche problem, but it might be the result of some other issue that could cause other problems.
I have created a minimal reproducible example, stemming from the iOS App template, with SwiftUI and SwiftData.
ContentView.swift
import SwiftUI
import SwiftData
struct ContentView: View {
@Environment(\.modelContext) private var modelContext
@Query private var items: [Item]
var body: some View {
NavigationStack {
TabView {
ForEach(items) { item in
Text(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))
}
}
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .automatic))
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
NavigationLink {
Button(action: {
modelContext.insert(Item(timestamp: Date()))
}) {
Text("Create Item")
}
} label: {
Text("Creation Page")
}
}
}
// When added, crashes the app
.navigationTitle("Crash")
}
}
}
TestingApp.swift (unchanged)
import SwiftUI
import SwiftData
@main
struct TestingApp: App {
var sharedModelContainer: ModelContainer = {
let schema = Schema([
Item.self,
])
let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false)
do {
return try ModelContainer(for: schema, configurations: [modelConfiguration])
} catch {
fatalError("Could not create ModelContainer: \(error)")
}
}()
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(sharedModelContainer)
}
}
Item.swift (unchanged)
import Foundation
import SwiftData
@Model
final class Item {
var timestamp: Date
init(timestamp: Date) {
self.timestamp = timestamp
}
}
Topic:
UI Frameworks
SubTopic:
SwiftUI
I reposted this issue from my previous post since I have a partial solution to it, and now have a more precise question. The previous post title was too broad.
My app is not Document-based, the UI is written with SwiftUI and I had to implement the 'Open Recent' menu myself. The class RecentDiscsModel has a refresh() function that forces the new opened file to be seen in the menu. Without that, the app needed to be restarted to see them. (The files were appearing in the Dock menu, however.)
My problem is, that when we open this 'Open Recent' menu, it closes when the UI is updating. My app being a Disc Player, the main and unique window UI is updating every second or more through many @Published properties from my AudioDiscPlayer class.
I have no idea how to prevent this issue.
@main struct MyApp: App
@main
struct MyApp: App {
@NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
@StateObject private var recentDiscsModel = RecentDiscsModel.shared
var body: some Scene {
Window("Player", id: "main-window") {
PlayerView()
}
.commands {
CommandGroup(replacing: .newItem) { }
CommandGroup(after: .newItem) {
Button("Open...") {
NotificationCenter.default.post(name: .openDocumentRequested, object: nil)
}
.keyboardShortcut("O", modifiers: .command)
if recentDiscsModel.recentDocs.isEmpty == false {
Menu("Open Recent") {
ForEach(NSDocumentController.shared.recentDocumentURLs, id: \.self) { url in
Button(url.lastPathComponent) {
global.insertDisc(at: url)
}
}
Divider()
Button("Clear Menu") {
NSDocumentController.shared.clearRecentDocuments(nil)
recentDiscsModel.refresh()
}
}
}
}
PlayBackMenu()
}
}
}
class RecentDiscsModel: ObservableObject | The class that handles the live refresh of the 'Open Recent' menu
class RecentDiscsModel: ObservableObject {
static let shared = RecentDiscsModel()
@Published private(set) var recentFiles: [URL] = []
private init() {
refresh()
}
func refresh() {
let newDocs = NSDocumentController.shared.recentDocumentURLs
if newDocs != recentDocs {
recentDocs = newDocs
}
}
}
class Globals: ObservableObject | This is the class that handling opening cueSheet file:
class Globals: ObservableObject {
static let shared = MCGlobals()
init() {}
@Published var errorMessage = ""
@Published var errorDetails = ""
@Published var showingErrorAlert = false
func handleFileImport(result: Result<URL, Error>) {
switch result {
case .success(let url):
guard url.startAccessingSecurityScopedResource() else {
errorMessage = "Unable to access file"
errorDetails = "Permission denied"
showingErrorAlert = true
return
}
defer { url.stopAccessingSecurityScopedResource() }
insertDisc(at: url)
case .failure(let error):
errorMessage = "Failed to import file"
errorDetails = error.localizedDescription
showingErrorAlert = true
}
}
func insertDisc(at url: URL, startPlayback: Bool = false) {
do {
try AudioDiscPlayer.shared.insertDisc(at: url, startPlayback: startPlayback)
NSDocumentController.shared.noteNewRecentDocumentURL(url)
} catch {
let nsError = error as NSError
errorMessage = nsError.localizedDescription
let reason = nsError.localizedFailureReason ?? ""
let recovery = nsError.localizedRecoverySuggestion ?? ""
errorDetails = "\n\n\(reason)\n\n\(recovery)".trimmingCharacters(in: .whitespacesAndNewlines)
showingErrorAlert = true
}
RecentDiscsModel.shared.refresh()
}
}
App freezes when using a SwiftUI Picker with pickerStyle(.segment), Images with .symbolRenderingMode(.palette) and try to show a sheet.
import SwiftUI
enum Sample: String, CaseIterable, Identifiable {
case aaa, bbb, ccc, ddd
var id: Self { self }
var image: Image {
switch self {
case .aaa: Image(systemName: "square.stack.3d.up.fill")
case .bbb: Image(systemName: "square.and.arrow.up")
case .ccc: Image(systemName: "square.and.arrow.up.fill")
case .ddd: Image(systemName: "square.and.arrow.down")
}
}
}
struct PickerBug: View {
@State private var selected: Sample = .aaa
@State var showSheet = false
var body: some View {
List {
Section {
VStack {
Picker("Qqq", selection: $selected) {
ForEach(Sample.allCases) { sample in
sample.image
// .symbolRenderingMode(.palette)
.foregroundStyle(.black)
}
}
.pickerStyle(.segmented)
}
}
Text("Aaa")
}
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
Button {
showSheet.toggle()
} label: {
Text("A")
}
}
}
.sheet(isPresented: $showSheet) {
Text("Aaaa")
}
}
}
#Preview {
NavigationStack {
PickerBug()
}
}
Uncomment .symbolRenderingMode(.palette) show the picker and the app freezes.
Xcode, Preview and Simulator, i could not test on a real device.
I'm having some trouble getting my widget to display how I want when the user has a tint applied to their home screen. The issue I'm having is with a Text() element, as well as a LinearGradient I am displaying on top of my image. The text should always be white, and the gradient is always black with varying levels of opacity.
I've managed to fix this issue with images displayed in my widget by leveraging
widgetAccentedRenderingMode(.fullColor)
however, there does not seem to be an equivalent of this for non-Image components. I'm aware of
.widgetAccentable(false)
but as I understand it, elements are already considered not accentable by default and you need to explicitly declare widgetAccentable(true) to add them to the accent group. I've tried specifying this to be false up and down my view hierarchy just to see if something will stick but no luck.
Are there any other levers I can pull to preserve the declared colors for my text and gradient components? The images I am displaying is album artwork where preserving the original image is integral, but the tinted text color and overlaid gradient often clash or just looks bad in general. Is there a solution for colored primitive elements?
Hello 👋
I played with the iOS 18 Group(subviews:) APIs these days and I guess I'm missing a point. Environment values seems to not being passed to subviews when set within the Group(subviews:) API.
See the following code:
Is it intended to be that way ? How to propagate different values to different subviews in this case ?
I heard of ContainerValues API but it seems to be a way to provide value at root level to access it during subview iteration. What I'm looking for is "insert"/"propagate" values to each subview during subview iteration.
PS:
This works but I have lost subview context this way (I'm out of the group).
Thanks in advance for anyone answering this!
Hi all,
We’re developing hybrid apps using the Ionic Framework and testing them on Xcode.
Recently, we tested our app on iOS 18.5 and 18.6 and noticed a strange issue: when trying to change elements like the range bar, the control only responds if we tap slightly above it. It seems like there’s a misalignment.
This problem didn’t occur on earlier iOS versions. Is anyone else experiencing similar issues?
Topic:
UI Frameworks
SubTopic:
SwiftUI
Was it always so tricky to ignore the bottom safe area? Seems like iOS 26 makes this much harder.
I've tried many variations of ignoresSafeArea, safeAreaInset, safeAreaBar, etc. Nothing seems to work. As soon as I add padding, the bottom safe area crashes the party.
This is what I want to achieve:
This is what I get right now:
struct ContentView: View {
var body: some View {
List {
Text("Content")
}
.overlay(alignment: .bottom) {
content
}
}
var content: some View {
VStack {
Text("Custom Container")
}
.frame(maxWidth: .infinity)
.frame(height: 400)
.background(Color.gray, in: .rect(corners: .concentric, isUniform: true))
.padding(15)
}
}
After reinstalling the App,the ControlWidget Gallery doesn't show custom SF Symbols
I want to display a grid of items in my widget similar to the systemLarge Shortcuts app widget. I use clipShape(.containerRelative) to get the widget corner radius, but items that do not touch a corner in any way do not get this treatment. This is even worse with the extra large widget. How can I apply the corner radius of the widget minus the padding across all items? It does not seem like the radius is exposed outside of that special shape.
Trying to get my iPad app to display a different view on connected external display.
Info.plist is setup as follows:
<dict>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<true/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleExternalDisplayNonInteractive</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>External Display</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
</dict>
</array>
</dict>
</dict>
</dict>
I have my SceneDelegate setup as the follows:
import SwiftUI
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = scene as? UIWindowScene else { return }
if session.role == .windowExternalDisplayNonInteractive {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: ExternalDisplayView())
self.window = window
window.makeKeyAndVisible()
}
}
}
I've tested running on a physical iPad with usb-c to hdmi connected and it only mirror's the screen. Same when connecting to AirPlay. Also tested running a simulator with external display enabled. Is there something I'm missing?
Topic:
UI Frameworks
SubTopic:
SwiftUI
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?
An WWDC 25 a neutral value was demonstrated that allows the Slider to be 'coloured in' from the point of the neutral value to the current thumb position. Trying to use this in Dev release 1 I get errors saying no such modifier.
Was this functionality released in Dev Release 1 or am I using it incorrectly?
I've already searched extensively on Apple Developer Forums and Stack Overflow, and didn't really find what I need or I missed it.
I'm developing a macOS music player app that uses cuesheet files paired with audio files. The core functionality is working, opening and playing files works without issues, but I'm struggling with implementing proper file handling features due to my limited experience with UI frameworks.
The current state of my app is intentionally simple:
Single window interface representing a music player with track list
Opening cuesheet files changes the “disc” and updates the window
Built with SwiftUI (not AppKit)
Not created as a Document-Based app since the user doesn't need to edit, save, or work with multiple documents simultaneously
What I Need to Implement:
Open Recent menu that actually works
Recent files accessible from Dock menu
Opening cuesheet files from Finder
Drag-and-drop cuesheet files onto app window (lower priority)
Problems I've Encountered:
I've tried multiple approaches but never achieved full functionality. The closest I got was an “Open Recent” menu that:
Only updated after app relaunch
Its drop-down kept closing while music was playing
My Questions
Is it possible purely in SwiftUI?
Is there documentation I'm missing? I feel like I might be overcomplicating this.
I'm open to alternative approaches if my current direction isn't ideal:
Should I redesign as Document-Based? Since I apparently need NSDocumentController, would it be better to start with a Document-Based app template and disable unwanted features, and how?
Should I mix AppKit with SwiftUI? While SwiftUI has been wonderful for my main window, it's becoming frustrating for other UI parts, especially menus. Would using AppKit for menus and keeping SwiftUI for the main interface be a reasonable approach?
I thought this would be straightforward:
Customize the .fileImporter with the proper logic of what to do with the files
Call NSDocumentController.shared.noteNewRecentDocumentURL(url) so the Open Recent menu is created a populated with opened files.
Maybe it really is that simple and I've gotten lost down a rabbit hole? UI programming is quite new to me, so I might be missing something obvious.
Any guidance, code examples, or pointing me toward the right documentation would be greatly appreciated!