MacOS system settings allow the user to select one of a number of number formats. My app behaves differently depending on the format (taken from the system Locale), so I need to test every combination.
Thus far I have been successful at creating Locale objects with various identifiers that map to the different formats, like:
let westEuropeanLocale = Locale(identifier: "en_DE")
However, I can't find a locale that maps to using . as a decimal point, and space as a thousands separator, even though it's a standard option (3rd in this list):
Any suggestions on how to create a test for this number format?
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
Activity
When you set inputAccessoryView AND inputView you get unexpected system UI in between the two custom views
If anyone has a workaround for this I'd love to hear it.
See also: https://stackoverflow.com/questions/79818015/uitextfield-custom-inputaccessoryview-with-custom-inputview-in-ios-26
Red == inputAccessoryView
Blue == inputView
Glassy bit in between == bug?
//
// ViewController.swift
// Custom Keyboard
//
// Created by Lewis Smith on 19/02/2026.
//
import UIKit
class ViewController: UIViewController {
let textField = {
let textField = UITextField()
textField.translatesAutoresizingMaskIntoConstraints = false
textField.backgroundColor = .yellow
let inputAccessoryView = UIView(frame: CGRect(x: 0, y: 0, width: .zero, height: 70))
inputAccessoryView.backgroundColor = .red
let inputView = UIView(frame: CGRect(x: 0, y: 0, width: .zero, height: 70))
inputView.backgroundColor = .blue
// When you set inputAccessoryView AND inputView you get unexpected UI inbetweeen the two custom views
textField.inputAccessoryView = inputAccessoryView
textField.inputView = inputView
textField.becomeFirstResponder()
return textField
}()
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .purple
self.view.addSubview(textField)
NSLayoutConstraint.activate([
textField.centerXAnchor.constraint(equalTo: view.centerXAnchor),
textField.centerYAnchor.constraint(equalTo: view.centerYAnchor),
textField.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
textField.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
])
}
}
It appears that starting with macOS Sequoia, Quick Look Preview extension no longer loads MapKit maps correctly anymore. Map tiles do not appear, leaving users with a beige background.
Users report that polylines do render correctly, but annotations appears black.
This was previously working fine in prior macOS versions including Sonoma.
STEPS TO REPRODUCE
Create a macOS app project, with an associated document.
Ensure project has a Quick Look preview extension, with necessary basic setups.
Ensure that the extension mentioned in (2) must have a MKMapView. Any other cosmetic changes, etc, does not need to be implemented to observe the base issue. Do note that it has been reported that in addition to the map tiles not loading, annotations don't render correctly as well.
Do you guys know how to fix the render of the text in the accessory view ? If I force the color of text to be .black it work but it will break dark mode, but forcing it .black : .white on color scheme changes makes white to still adapt to what is behind it I have noticed that Apple Music doesn’t have that artifact and it seems to break when images are behind the accessory view
// MARK: - Next Routine Accessory
@available(iOS 26.0, *)
struct NetxRoutinesAccessory: View {
@ObservedObject private var viewModel = RoutineProgressViewModel.shared
@EnvironmentObject var colorSchemeManager: ColorSchemeManager
@EnvironmentObject var routineStore: RoutineStore
@EnvironmentObject var freemiumKit: FreemiumKit
@ObservedObject var petsStore = PetsStore.shared
@Environment(\.colorScheme) private var colorScheme
// Tab accessory placement environment
@Environment(\.tabViewBottomAccessoryPlacement) private var accessoryPlacement
// Navigation callback
var onTap: (() -> Void)?
@State private var isButtonPressed = false
/// Explicit black for light mode, white for dark mode
private var textColor: Color {
colorScheme == .dark ? .trueWhite : .trueBlack
}
/// Returns true when the accessory is in inline/minimized mode
private var isInline: Bool {
accessoryPlacement == .inline
}
var body: some View {
accessoryContent()
.onTapGesture {
onTap?()
}
}
private func accessoryContent() -> some View {
HStack(spacing: 12) {
// Content with smooth transitions
VStack(alignment: .leading, spacing: 2) {
if viewModel.totalTasks == 0 {
Text(NSLocalizedString("Set up routines", comment: "Routines empty state"))
.font(.subheadline.weight(.medium))
.foregroundColor(textColor)
} else if let next = viewModel.nextRoutineTask() {
HStack(spacing: 4) {
Text(NSLocalizedString("Next", comment: "Next routine prefix"))
.font(.caption)
.foregroundColor(textColor)
Text("•")
.font(.caption)
.foregroundColor(textColor)
Text(next.routine.name)
.font(.subheadline.weight(.medium))
.foregroundColor(textColor)
.lineLimit(1)
}
.id("routine-\(next.routine.id)-\(next.time)")
.transition(.opacity.combined(with: .move(edge: .leading)))
HStack(spacing: 4) {
Text(viewModel.petNames(for: next.routine.petIDs))
.font(.caption)
.foregroundColor(textColor)
Text("•")
.font(.caption)
.foregroundColor(textColor)
Text(Routine.displayTimeFormatter.string(from: next.time))
.font(.caption.weight(.medium))
.foregroundColor(colorSchemeManager.accentColor ?? .blue)
}
.id("time-\(next.routine.id)-\(next.time)")
.transition(.opacity.combined(with: .move(edge: .leading)))
} else {
// All tasks completed
Text(NSLocalizedString("All done for today!", comment: "All routines completed"))
.font(.subheadline.weight(.medium))
.foregroundColor(textColor)
.transition(.opacity.combined(with: .scale))
Text("\(viewModel.completedTasks)/\(viewModel.totalTasks) " + NSLocalizedString("tasks", comment: "Tasks count suffix"))
.font(.caption)
.foregroundColor(textColor)
}
}
.animation(colorSchemeManager.reduceMotion ? nil : .snappy(duration: 0.3), value: viewModel.completedTasks)
.animation(colorSchemeManager.reduceMotion ? nil : .snappy(duration: 0.3), value: viewModel.progress)
}
.padding()
.contentShape(.rect)
.animation(colorSchemeManager.reduceMotion ? nil : .snappy(duration: 0.35), value: viewModel.completedTasks)
}
}
Topic:
UI Frameworks
SubTopic:
SwiftUI
When disabling the opacity slider of color panels, my app crashes with unsatisfiable layout constraints. Feel free reproduce with a minimal test project: A macOS app based on the Xcode 26.0 template with only one line added to the ViewController's viewDidLoad() function:
NSColorPanel.shared.showsAlpha = false
The issue doesn't occur if this property is set to "true" or not set at all.
I just filed a corresponding bug report (FB20269686), although I don't expect any feedback from Apple ... as numerous issues I reported were never updated or commented at all (after migrating from RADARs).
Topic:
UI Frameworks
SubTopic:
AppKit
I'm developing a turn-based Messages game extension and experiencing a persistent issue on iPad where tapping on message bubbles does not reliably trigger lifecycle callbacks after the extension has been used once.
The Problem:
On iPad, after a player:
Opens the extension by tapping a game message
Takes their turn (plays a card)
Sends the updated game state as a new message
Extension collapses
When the opponent sends their response and the player taps on the new message bubble, the extension often does not open. The didSelect(_:conversation:) method is not called. The user must refresh the conversation by scrolling away and back or reopening the Messages App before tapping works again. This works perfectly on iPhone - every tap on a message bubble reliably triggers didSelect and opens the extension.
What I've Tried:
I've implemented every lifecycle method and workaround I could find:
swiftoverride func willBecomeActive(with conversation: MSConversation) {
super.willBecomeActive(with: conversation)
if let message = conversation.selectedMessage, let url = message.url {
loadGameState(from: url, message: message, conversation: conversation)
}
}
override func didBecomeActive(with conversation: MSConversation) {
super.didBecomeActive(with: conversation)
if let message = conversation.selectedMessage, let url = message.url {
loadGameState(from: url, message: message, conversation: conversation)
}
}
override func didSelect(_ message: MSMessage, conversation: MSConversation) {
// This is NOT called on iPad when tapping message bubbles
guard let url = message.url else { return }
loadGameState(from: url, message: message, conversation: conversation)
}
override func didReceive(_ message: MSMessage, conversation: MSConversation) {
guard let url = message.url else { return }
loadGameState(from: url, message: message, conversation: conversation)
}
override func didTransition(to presentationStyle: MSMessagesAppPresentationStyle) {
super.didTransition(to: presentationStyle)
// Attempted to reload here as well
}
I also tried:
Observing NSExtensionHostDidBecomeActive and NSExtensionHostWillEnterForeground notifications
Forcing UI refresh in viewDidLayoutSubviews
Checking conversation.selectedMessage in every lifecycle method
Research:
I found several Developer Forums threads from 2016 describing this exact issue:
Thread 53167: "MSMessagesAppViewController.didSelect not called on message reselect"
Thread 60323: "willSelectMessage and didSelectMessage don't fire"
An Apple staff member confirmed that didSelect only fires when selecting a different message, similar to UITableView selection behavior. However, on iPad, it seems like messages remain "selected" even after the extension collapses, so tapping a new message doesn't register as a new selection.
Questions:
Is there a recommended way to detect when a user taps a message bubble on iPad, even if iOS considers a message "already selected"?
Is there a way to programmatically deselect the current message (similar to UITableView.deselectRow) so that subsequent taps trigger didSelect?
Are there any iPad-specific lifecycle methods or notifications I should be observing?
Is this a known limitation of the Messages framework on iPad?
Environment:
Xcode 16
iOS 18 and 26
Testing on iPad Pro (M4) and iPad Air
iPhone works correctly on all tested devices
Any guidance would be greatly appreciated. This is blocking our App Store submission as reviewers are flagging the iPad behavior as incomplete functionality.
I have no idea how to do it: on MacOS, in Document.init(configuration: ReadConfiguration) I decode file, and restore objects from data, which in some cases could take a long time. Document isn't fully inited, so I have no access to it. But would like to have a progress bar on screen (easier to wait for done, for now). I know size, progress value, but no idea how to make view from object during init.
I know, this question may be very stupid.
init(configuration: ReadConfiguration) throws {
guard let data = configuration.file.regularFileContents
else {
throw CocoaError(.fileReadCorruptFile)
}
let decoder = JSONDecoder()
let flat = try decoder.decode(FlatDoc.self, from: data)
print ("reverting \(flat.objects.count) objects...")
///This takes time, a lot of time, need progress bar
///Total is `flat.objects.count`, current is `objects.count`
/// `Show me a way to the (next) progress bar!`
revertObjects(from: flat.objects)
print ("...done")
}
update: I defined var flatObjects in Document, and I can convert in .onAppear.
struct TestApp: App {
@State var isLoading = false
...
ContentView(document: file.$document)
.onAppear {
isLoading = true
Task {file.document.revertObjects()}
isLoading = false
}
if isLoading {
ProgressView()
}
...
}
But progress bar never shows, only rainbow ball
Is there a way to render stereoscopic (left/right) images in a 2d plane that resides in a swiftUI view?
I know this is possible in realityKit shaders, and in immersive metal composits, but is it possible via swiftUI shaders, CAMetalLayer, etc?
I'd like to draw a 2d window with standard UI chrome (resize, move etc) that displays stereoscopic content on the flat plane of the window.
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
In iOS 18, TabView with .tabViewStyle(.sidebarAdaptable) introduced a powerful adaptive pattern — tabs in compact, sidebar in regular. However, the current Tab API only supports a title and an image (icon). There is no way to provide a trailing accessory view (e.g., a secondary icon or indicator) for sidebar rows.
This is a meaningful gap in the API, because trailing accessories are a well-established pattern throughout UIKit and SwiftUI.
Precedent in Apple's own design language
Apple already supports trailing accessories in many analogous contexts:
UITableViewCell / UICollectionViewListCell — support accessories (disclosure indicators, checkmarks, custom views) via UICellAccessory.
UIListContentConfiguration — allows leading and trailing content in list rows.
SwiftUI List rows — support Label, HStack with trailing elements, .badge(), and swipeActions.
NavigationLink — automatically renders a disclosure chevron as a trailing accessory.
UITabSidebarItem (UIKit, iOS 18) — supports configurationUpdateHandler and cell accessories at the UIKit level.
The sidebar of a .sidebarAdaptable TabView is visually identical to a List — yet its rows lack the accessory support that List rows have had for years.
Real-world example: Photos app
Apple's own Photos app (iPadOS 18+) demonstrates this exact need. In its sidebar, the "Recently Deleted" row displays a trailing lock icon to indicate that authentication is required to view the album. This is a meaningful UX element — it communicates state at a glance, without requiring the user to tap into the item.
Third-party developers building with TabView(.sidebarAdaptable) have no public API to replicate this pattern. The Tab view builder's label closure is decomposed into a discrete title and image; any additional views (including Spacer() and trailing Image views within an HStack) are silently discarded by the system.
What we've tried
Custom label closure with HStack — trailing views are ignored. The system extracts only the first Image and Text.
.badge() modifier — only supports Int or Text, not custom views such as icons.
Label with complex content — the system normalizes it to icon + title.
The only viable path today is to bridge to UIKit's UITabBarController and customize UITabSidebarItem directly, which defeats the purpose of using SwiftUI's declarative TabView API.
Proposed API
A trailing accessory modifier on Tab, consistent with existing SwiftUI patterns:
Tab("Recently Deleted", systemImage: "trash", value: "deleted") {
RecentlyDeletedView()
}
.tabSidebarAccessory {
Image(systemName: "lock.fill")
.foregroundStyle(.secondary)
}
// Option B: Text accessory (e.g., counts, status labels)
Tab("Inbox", systemImage: "tray", value: "inbox") {
InboxView()
}
.tabSidebarAccessory {
Text("12")
.font(.subheadline)
.foregroundStyle(.secondary)
}
// Option C: Combined text + image accessory
Tab("Shared Albums", systemImage: "rectangle.stack", value: "shared") {
SharedAlbumsView()
}
.tabSidebarAccessory {
HStack(spacing: 4) {
Text("3 new")
.font(.caption)
.foregroundStyle(.secondary)
Image(systemName: "person.2.fill")
.foregroundStyle(.blue)
}
}
Environment
Platform: iPadOS / macOS Catalyst
iOS version: 18.0+
Xcode: 16.0+
Component: SwiftUI TabView with .tabViewStyle(.sidebarAdaptable)
Summary
The Tab API should support trailing accessory content for sidebar rows, bringing it in line with the accessory support already available in UITableViewCell, UICollectionViewListCell, UIListContentConfiguration, and SwiftUI List. Apple's own Photos app demonstrates the need for this capability, yet no public API exists for third-party developers to achieve it.
Any logical reason why applying .sharedBackgroundVisibility(.hidden) to a ToolbarItem would not remove the spacing allocated for glass border?
Thus causing any element utilizing this functionality to appear offset from the regular buttons.
Or is this yet another magical Apple experience I am not blessed enough to understand.
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 everyone,
I’m running into a strange issue with UISearchController placement with iOS 26 SDK.
In one of my view controllers, I was able to move the search bar to the top of the navigation bar by setting:
navigationItem.searchController = searchController
navigationItem.hidesSearchBarWhenScrolling = false
navigationItem.preferredSearchBarPlacement = .stacked
This works as expected — the search bar is placed at the top.
However, in another view controller with almost identical configuration, the search bar always shows up at the bottom. If I delay the setup with DispatchQueue.main.async, it appears at the bottom; if I don’t, it doesn’t appear at all. Both VCs are wrapped in their own UINavigationController.
So my questions are:
Has anyone faced this issue where preferredSearchBarPlacement = .stacked is ignored?
Are there hidden requirements or limitations for placing the search bar at the top?
Why could the same setup behave differently in two controllers?
Any help or ideas would be appreciated!
When you share a Url from any Google product, it creates a share.google minify Url. When iMessage fetch the Url meta headers, it receives the og:title, og:url, og:site_name, og:image. But it only show the preview card with og:image, og:title, and og:site_name, ignoring the value of og:description.
I'm using one UITabBarController which leads to 6 NavigationController. Therefore the user will get 4 icons displayed and one icon with three points to see the rest of the Navigation Controller.
If the user now tries to edit the list and moves one item from the hidden area towards the TabBar at the bottom, the App crashes with the error:
Exception
NSException * "Can't add self as subview" 0x0000600000d16040
I can see this effect at least on both my apps.
If the same compilation is run on a older iOS version, there is no crash.
Is there anything I have to take care of the configuration of the TabBar, when it comes to iOS26?
Topic:
UI Frameworks
SubTopic:
UIKit
Description:
I’m encountering an issue where the Apple Watch’s watchOS version is lower than the deployment target specified in my Xcode project.
For example, my Watch device is running watchOS 10.6, but my app’s deployment target is set to watchOS 9.6 or 10.6, and Xcode shows an error stating:
Error: “watchOS version doesn’t match the app’s deployment target.”
Could someone clarify how to properly handle this version mismatch?
Environment:
Xcode 26
iPhone: iOS 18
Apple Watch: watchOS 10.6
Any guidance or best practices would be appreciated.
When building in Xcode on MacOS Tahoe, it seems it is no longer possible to dynamically specify a "small" size toolbar for NSToolbar/NSToolbarItem. It works in MacOS code compiled and linked on earlier systems.
I don't want to use "SFSymbol", or "templates". I have over 60 custom-made .png toolbars, in individual Image Set files, at the previous requisite sizes of 24x24 / 48x48, and 32x32 / 64x64.
Sure -- I can configure an NSToolbar with whatever size .png assets I want. I just can't dynamically switch between the two groups of sizes.
According to the Apple Coding Assistant, the only solution is to change the image names of each of the NSToolbarItems at runtime.
OK -- but even when attempting that, the NSToolbarItems refuse to take on their smaller size...
...unless: they are attached to a custom view NSToolbarItem with an NSButton of style "Bevel". I have about 10 of those, and YES -- I CAN change those to a "small" size. Is this REALLY what I'm forced to do?!
The Apple Coding Assistant just runs me around in circles, making coding suggestions that include properties that don't exists.
I've gone around and around on these issues for over a week -- it can't be this hard, right? Is there no way to make multiple NSToolbar objects, one for "large" and one for "small"?
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.
We are currently testing our application under macOS 26 in Liquid Glass mode and noticed an issue with NSSegmentedCell.
Our app makes extensive use of NSCell-based drawing. Since macOS 26, when running in Liquid Glass mode, NSSegmentedCell does not render at the expected location.
The control itself appears visually correct, but it is clearly drawn offset from the rect it is supposed to occupy.
In compatibility mode, everything renders exactly as expected (same code, same layout).
To illustrate the issue, here are two screenshots of the same view:
Liquid Glass mode
👉 (screenshot 1 – segmented control visibly shifted)
Compatibility mode
👉 (screenshot 2 – correct rendering)
The regression is obvious when switching between the two modes.
This behavior has been present since the first macOS 26 release and is still reproducible with Xcode 26.2 (17C52).
I have already filed a report via Feedback Assistant (FB reference available if useful), but I’m posting here to see whether others are experiencing the same issue or have found a workaround.
Thanks.
Topic:
UI Frameworks
SubTopic:
AppKit
Problem
After launching the host app by tapping the widget (widgetURL), calls to:
WidgetCenter.shared.reloadAllTimelines() WidgetCenter.shared.reloadTimelines(ofKind: ...)
are ignored/deferred for an initial period right after the app opens. During this window, the widget does not reload its timeline and remains unupdated, no matter how many times I call the reload methods. After some time passes (typically ~30 seconds, sometimes shorter/longer), reload calls start working again.
There is also no developer-visible signal (no callback/error/acknowledgement) that the reload was ignored, so the app can’t detect the failure and can’t reliably recover the flow.
Question: Is this expected behavior (throttling/cooldown) after opening the app from a widget ? If so, is there any recommended workaround to update the widget reliably and quickly (or at least detect that the reload was not accepted)?
Any guidance would help.