import SwiftUI
struct ContentView: View {
@State private var selection = 1
var body: some View {
TabView(selection: $selection) {
Tab("1", systemImage: "1.circle", value: 1) {
Text("Tab 1")
}
Tab("2", systemImage: "2.circle", value: 2) {
Text("Tab 2")
}
}
.tabViewBottomAccessory {
if selection == 1 {
Text("Bottom Bar for Tab 1")
}
}
}
}
With this structure, I'm supposing when I select tab 2, the bottom accessory will be hidden, but it is not hidden for the first time, after I click back to tab 1, then click tab 2, it is hidden.
I think this is a bug?
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
My app displays some text that should appear the same regardless of the container view or window size, i.e. it should grow and shrink with the container view or window.
On iOS there is UILabel.adjustsFontSizeToFitWidth but I couldn't find any equivalent API on macOS. On the internet some people suggest to iteratively set a smaller font size until the text fits the available space, but I thought there must be a more efficient solution. How does UILabel.adjustsFontSizeToFitWidth do it?
My expectation was that setting a font's size to a fraction of the window width or height would do the trick, but when resizing the window I can see a slightly different portion of it.
class ViewController: NSViewController {
override func loadView() {
view = MyView(frame: CGRect(x: 0, y: 0, width: 400, height: 400))
NSLayoutConstraint.activate([view.widthAnchor.constraint(equalTo: view.heightAnchor, multiplier: 3), view.heightAnchor.constraint(greaterThanOrEqualToConstant: 100)])
}
}
class MyView: NSView {
let textField = NSTextField(labelWithString: String(repeating: "a b c d e f g h i j k l m n o p q r s t u v w x y z ", count: 2))
override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
textField.translatesAutoresizingMaskIntoConstraints = false
textField.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
addSubview(textField)
NSLayoutConstraint.activate([textField.topAnchor.constraint(equalTo: topAnchor), textField.leadingAnchor.constraint(equalTo: leadingAnchor), textField.trailingAnchor.constraint(equalTo: trailingAnchor)])
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func resize(withOldSuperviewSize oldSize: NSSize) {
// textField.font = .systemFont(ofSize: frame.width * 0.05)
textField.font = .systemFont(ofSize: frame.height * 0.1)
}
}
Hi,
I have trouble changing the color of the text of Link in SwiftUI. I tried with this code:
Link("https://www.mylink.com/", destination: URL(string: "https://www.mylink.com/")!)
.foregroundColor(Color.green)
and this code:
HStack(spacing: 0) {
Link("https://www.mylink.com/", destination: URL(string: "https://www.mylink.com/")!)
}
.foregroundColor(Color.green)
The link keeps getting the accent color.
EDIT:
I want to add that it used to work and I think the issue came with a beta of Xcode 26. I think that was around the beta 4 or beta 5.
Is it a change of the APIs or a bug?
Topic:
UI Frameworks
SubTopic:
SwiftUI
When I set up UIScrollEdgeElementContainerInteraction for a UITableView in iOS 26 like this:
let interaction = UIScrollEdgeElementContainerInteraction()
interaction.scrollView = tableView
interaction.edge = .top
viewHeader.addInteraction(interaction)
the section header remains displayed above the gradient glass effect, but the cells do not exhibit this issue.
Visually, the cells appear beneath the glass layer, while the header appears above the glass layer—even though, in reality, both the header and the cells are positioned below the glass layer in the view hierarchy.
When I set up UIScrollEdgeElementContainerInteraction for a UITableView in iOS 26 like this:
let interaction = UIScrollEdgeElementContainerInteraction()
interaction.scrollView = tableView
interaction.edge = .top
viewHeader.addInteraction(interaction)
the section header remains displayed above the gradient glass effect, but the cells do not exhibit this issue.
I’m seeing what looks like a regression on iOS 26 beta where a presented view controller dismisses when a user long‑presses a button inside a table view cell and drags downward.
Steps to reproduce
Present a UIViewController modally.
The controller contains a UITableView; each cell has a UIButton.
Long‑press and hold the UIButton in any cell.
While still holding, drag downward.
Expected
The button and/or table view handle the gesture; no interactive dismissal starts.
Actual
The system recognizes a pull‑to‑dismiss gesture and begins dismissing the presented controller.
Notes
Reproducible only on iOS 26 beta.
Not observed on earlier iOS versions in my testing.
Happens on both simulator and device (beta).
Environment
iOS: 26 beta (please see exact build)
I have SwiftData models containing arrays of Codable structs that worked fine before adding CloudKit capability. I believe they are the reason I started seeing errors after enabling CloudKit.
Example model:
@Model
final class ProtocolMedication {
var times: [SchedulingTime] = [] // SchedulingTime is Codable
// other properties...
}
After enabling CloudKit, I get this error logged to the console:
'NSKeyedUnarchiveFromData' should not be used to for un-archiving and will be removed in a future release
CloudKit Console shows this times data as "plain text" instead of "bplist" format.
Other struct/enum properties display correctly (I think) as "bplist" in CloudKit Console.
The local SwiftData storage handled these arrays fine - this issue only appeared with CloudKit integration.
What's the recommended approach for storing arrays of Codable structs in SwiftData models that sync with CloudKit?
I am observing an unexpected behavior with external keyboard input on iOS.
When I press Command + key (e.g., ⌘ + J) while a UITextView is focused, the system invokes
pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?)
twice:
-> Once with the key press event without any modifier flags.
-> A second time with the same key event but including the Command modifier flag.
This behavior is checked on an iPad with an external keyboard.
Additionally, I noticed that textView(_:shouldChangeTextIn:replacementText:) is not invoked in this case, even if I call super.pressesBegan for event propagation.
Questions:
Is it expected that pressesBegan fires twice for a Command + key combination?
If so, what is the recommended way to distinguish between these two invocations?
Should the UITextView delegate methods (like shouldChangeTextIn) be triggered for such key combinations, or is this by design?
(Using macOS 26 Beta 9 and Xcode 26 Beta 7) I am trying to support basic onDrop from a source app to my app. I am trying to get the closest "source" representation of a drag-and-drop, e.g. a JPEG file being dropped into my app shouldn't be converted, but stored as a JPEG in Data. Otherwise, everything gets converted into TIFFs and modern iPhone photos get huge. I also try to be a good app, and provide asynchronous support.
Alas, I've been running around for days now, where I can now support Drag-and-Drop from the Finder, from uncached iCloud files with Progress bar, but so far, drag and dropping from Safari eludes me.
My code is as follows for the onDrop support:
Image(nsImage: data.image).onDrop(of: Self.supportedDropItemUTIs, delegate: self)
The UTIs are as follows:
public static let supportedDropItemUTIs: [UTType] = [
.image,
.heif,
.rawImage,
.png,
.tiff,
.svg,
.heic,
.jpegxl,
.bmp,
.gif,
.jpeg,
.webP,
]
Finally, the code is as follows:
public func performDrop(info: DropInfo) -> Bool {
let itemProviders = info.itemProviders(for: Self.supportedDropItemUTIs)
guard let itemProvider = itemProviders.first else {
return false
}
let registeredContentTypes = itemProvider.registeredContentTypes
guard let contentType = registeredContentTypes.first else {
return false
}
var suggestedName = itemProvider.suggestedName
if suggestedName == nil {
switch contentType {
case UTType.bmp: suggestedName = "image.bmp"
case UTType.gif: suggestedName = "image.gif"
case UTType.heic: suggestedName = "image.heic"
case UTType.jpeg: suggestedName = "image.jpeg"
case UTType.jpegxl: suggestedName = "image.jxl"
case UTType.png: suggestedName = "image.png"
case UTType.rawImage: suggestedName = "image.raw"
case UTType.svg: suggestedName = "image.svg"
case UTType.tiff: suggestedName = "image.tiff"
case UTType.webP: suggestedName = "image.webp"
default: break
}
}
let progress = itemProvider.loadInPlaceFileRepresentation(forTypeIdentifier: contentType.identifier) { url, _, error in
if let error {
print("Failed to get URL from dropped file: \(error)")
return
}
guard let url else {
print("Failed to get URL from dropped file!")
return
}
let queue = OperationQueue()
queue.underlyingQueue = .global(qos: .utility)
let intent = NSFileAccessIntent.readingIntent(with: url, options: .withoutChanges)
let coordinator = NSFileCoordinator()
coordinator.coordinate(with: [intent],
queue: queue) { error in
if let error {
print("Failed to coordinate data from dropped file: \(error)")
return
}
do {
// Load file contents into Data object
let data = try Data(contentsOf: intent.url)
Dispatch.DispatchQueue.main.async {
self.data.data = data
self.data.fileName = suggestedName
}
} catch {
print("Failed to load coordinated data from dropped file: \(error)")
}
}
}
DispatchQueue.main.async {
self.progress = progress
}
return true
}
For your information, this code is at the state where I gave up and sent it here, because I cannot find a solution to my issue.
Now, this code works everywhere, except for dragging and dropping from Safari.
Let's pretend I go to this web site:
https://commons.wikimedia.org/wiki/File:Tulip_Tulipa_clusiana_%27Lady_Jane%27_Rock_Ledge_Flower_Edit_2000px.jpg
and I try to drag-and-drop the image, it will fail with the following error:
URL https://upload.wikimedia.org/wikipedia/commons/c/cf/Tulip_Tulipa_clusiana_%27Lady_Jane%27_Rock_Ledge_Flower_Edit_2000px.jpg is not a file:// URL.
And then, fail with the dreaded
Failed to get URL from dropped file: Error Domain=NSItemProviderErrorDomain Code=-1000
As far as I can tell, the problem lies in the opaque NSItemProvider receiving a web site URL from Safari. I tried most solutions, I couldn't retrieve that URL. The error happens in the callback of loadInPlaceFileRepresentation, but also fails in loadFileRepresentation. I tried hard-requesting a loadObject of type URL, but there's only one representation for the JPEG file. I tried only putting .url in the requests, but it would not transfer it.
Anyone solved this mystery?
I have an app where the user can choose if the dark / light mode is enabled automatically during the night / day (dusk and dawn times are calculated according to to the date and location of the user).
I also have an UITabBarController, with two tabs which have a GMSMapView (Google Map View from their SDK), and three tabs with UITableViews.
I have noticed that when the automatic change of dark / light mode is performed from dark to light mode, and the user is in a tab with GMSMapView, the tabBar does not change to light model, it remains in dark mode.
I perform the switch by setting the self.window.overrideUserInterfaceStyle of the UIWindow of the UIScene. All the views change to light mode, including the navigation bar, but not the tab bar. If I move between the tabs with GMSMapView, the tabBar stays in dark mode. As soon as I move to a tab which contains a UITableView, the tabBar switches to light mode.
If the switch to light mode is performed while the user is in tab with the UITableViews, the tabBar switches to light mode immediately, as expected. When moving to the tabs with the GMSMapViews, the tabBar stays in light mode, also as expected.
I have also noticed the same problem in CarPlay, in CPMapTemplate (with a UIViewController whose view is GMSMapView), in the buttons with are set with the property “mapButtons”, and with the panning buttons. When the switch from dark mode to light mode is performed by setting the self.window.overrideUserInterfaceStyle of the UIWindow of CarPlay scene, the mapButtons keeps the glyphs in white, and set the background of the buttons to almost white, so the glyphs are barely visible unless you put png images on them instead of SF Symbols.
With the panning buttons there is not workaround, since you cannot set custom images for the panning buttons. This happens even if the panning buttons are not being displayed when the switch is performed to light mode, and you enable them later.
Is this a bug? Why does this only happen with view over GMSMapView (Google Maps view for a map from their SDK)? Can you think of any viable workaround?
Thank you.
In my own fairly complex DocumentGroup app, I've been having a problem with bottom bar items appearing briefly when first drawn, and then disappearing. This seems to be caused by the invalidation of one or more views in the hierarchy.
In Apple's own WritingApp, which is designed to demonstrate DocumentGroup, adding a bottom bar item to the toolbar demonstrates the problem:
This toolbar is on the StoryView:
ToolbarItem() {
Button("Show Story", systemImage: "book") {
isShowingSheet.toggle()
}
.sheet(isPresented: $isShowingSheet) {
StorySheet(story: document.story, isShowingSheet: $isShowingSheet)
.presentationSizing(.page)
}
}
// This does not persist
ToolbarItem(placement: .bottomBar) {
Button("Foo") { }
}
}
My 'Foo' button is new. What happens is that it persists for a few seconds; its disappearance coincides with the writing of the file to disk, it seems. I would dearly like it to persist! I've tried adding an ID, setting the toolbar visibility and so on, but no luck. Anyone had this working?
Topic:
UI Frameworks
SubTopic:
SwiftUI
My app controls the cursor movement in a text view on iPhone and iPads.
On screen touch, the IOS cursor position is out of sync with the app cursor position.
Is there a way to find out, on screen touch, where the ios cursor positition is and update the app cursor to the ios cursor position?
When they are out of sync, the user has to move the cursor to the startIndex and navigate from there. Frustating!
I have looked at many programming books, forums, and internet search with nothing to no avail.
Any help will be greatly appreciated. The app names are SummaGramPhonex and SummaGramIPAD11 and SummaGramIPAD13.
Thanks. Charlie
3Sep25
I want to check if this behaviour is legit in iOS 26 Beta:
We have an admittedly stranger setup where a child view controller acts as a TabBar and is a UIHostingController so that we can use SwiftUI for the tab bar items.
One of the tab pages has a scrollview whose content (imagine a chat view) might go from a lighter aspect to darker colors and back when scrolling.
When we scroll to predominantly dark bubbles, the trait of the tabBar changes to dark mode.
The function traitCollectionDidChange() on the UIHostingController is called ! but only for the tabBar controller.
I know that in iOS there is some blending going on at the tabBar level when scrolling, but changing just one view + subviews to dark mode, automatically, instead of user triggered? It might be some optimisation if the view is considered opaque? But then I would expect to not change anything visually, if opaque.
Is this expected behaviour on iOS 26?
And if so, can we disable it? But just this blending/ trait changing, and keep the user triggered trait changes.
Topic:
UI Frameworks
SubTopic:
SwiftUI
When using a NavigationSplitView in a DocumentGroup, SwiftUI renders incorrect UI and doesn’t let the user navigation between the sidebar and detail views.
Even the default Xcode project template “Document App” doesn’t work.
Steps to reproduce
Create a new project and use the Document App template.
Run the project on either iPad or iPhone running iOS 26 beta 9
Experience the following issues.
On iPhone
The back button (to return to the document browser) and the document title are rendered two times.
When viewing the detail of an item, by navigating to the detail view, you cannot go back to the list of items, because the back button brings you back to the document browser.
The same issues are also present on iPad.
I've tested this on an iPad and iPhone running iOS 26 beta 9 and Xcode 26.0 beta 7.
I've reported this issue already → FB20062294
Topic:
UI Frameworks
SubTopic:
SwiftUI
The design of VNDocumentCameraViewController has been updated with iOS 26. Now the 'done' button that appears when at least one page has been scanned is by default in blue (liquid glass).
Changing the navBar or the barButtonItems tintColor does not work.
So, how does one change the color of this button to match the app's color?
Thank you very much!
I’m facing an issue and I’d like to know if anyone has already run into this.
I have a ContentView that presents a SettingsView as a sheet. SettingsView applies a change to the app’s colorScheme. ContentView reacts correctly to the change, and SettingsView does too (so far, so good).
What’s strange is that when I set nil on the preferredColorScheme modifier (which, according to the docs, corresponds to the system color scheme), ContentView correctly picks up the change and refreshes, while SettingsView does pick up the change but doesn’t refresh. (In the video you can clearly see that when I switch from Dark to System, the parent view refreshes properly but not the presented sheet.)
I’ve tried everything—switching to UIKit, changing the sheet’s ID… nothing works
Another strange thing: if I present SettingsView through a NavigationLink, everything works normally…
Here is a sample code to reproduce:
import SwiftUI
enum AppTheme: Int {
case system = 0
case dark = 1
case light = 2
var colorScheme: ColorScheme? {
switch self {
case .system: return nil
case .light: return .light
case .dark: return .dark
}
}
}
struct SettingsView: View {
@AppStorage("theme") var appTheme: AppTheme = .system
var body: some View {
VStack(spacing: 8) {
Button {
select(theme: .system)
} label: {
Text("Systeme")
}
Button {
select(theme: .dark)
} label: {
Text("Dark")
}
Button {
select(theme: .light)
} label: {
Text("Light")
}
}
.preferredColorScheme(appTheme.colorScheme)
}
func select(theme: AppTheme) {
appTheme = theme
}
}
struct ContentView: View {
@AppStorage("theme") var appTheme: AppTheme = .system
@State var isPresented = false
var body: some View {
NavigationStack {
VStack {
Button {
isPresented = true
} label: {
Text("Present settings")
}
// NavigationLink("Present settings") {
// SettingsView()
// }
}
.preferredColorScheme(appTheme.colorScheme)
.sheet(isPresented: $isPresented) {
SettingsView()
}
}
}
}
#Preview {
ContentView()
}
Hi everyone!
I've encountered an issue on Mac Catalyst: using the latest inspector modifier causes abnormal Sidebar and Columns state in NavigationSplitView.
Sample Code:
struct ContentView: View {
@State private var isPresented = false
var body: some View {
NavigationSplitView {
List {
ForEach(0..<20, id: \.self) { item in
Text("Item \(item)")
}
}
} content: {
List {
ForEach(0..<20, id: \.self) { item in
Text("Item \(item)")
}
}
} detail: {
List {
}
}
.inspector(isPresented: $isPresented) {
Form {
}
}
}
}
Steps to reproduce:
Xcode 16 beta 7, create a new iOS project
Paste the code above
Enable Mac Catalyst
Run on Mac (macOS 15 beta 9)
Press Command+N three times to open 3 new windows
Click the Sidebar Toggle button
The issue occurs (see screenshot below)
Through testing, I found that as long as the inspector modifier is attached, the issue occurs.
Also, the problem only appears in the 3rd and subsequent newly opened windows—the first two windows work as expected.
FB20061521
Widget abnormal refresh
My app is a music application. When playing or pausing a song, the status is synchronized to NowPlaying, and the app itself supports widgets. During testing, I found that when pausing or playing music, the widget triggers a timeline refresh, which is completely unexpected. However, switching songs does not cause this.
Looking at Apple’s logs:
By default 21:27:08.094490+0800 mediaremoted Set: origin-iPhone-1280262988/client-com.company.musicdev-10059 (music)/player-MediaRemote-DefaultPlayer setting inferred playback state from to
By default 21:27:08.094607+0800 mediaremoted [MRDNowPlayingPlayerClient] PlaybackState changed from Playing to Paused for origin-iPhone-1280262988/client-com.company.musicdev-10059 (music)/player-MediaRemote-DefaultPlayer
By default 21:27:08.094713+0800 mediaremoted [MRDNowPlayingPlayerClient] isPlaying changed to false for origin-iPhone-1280262988/client-com.company.musicdev-10059 (music)/player-MediaRemote-DefaultPlayer
By default 21:27:08.111861+0800 mediaremoted Posted Active Now Playing Notification kMRMediaRemoteNowPlayingApplicationPlaybackStateDidChangeNotification for path origin-iPhone-1280262988/client-com.company.musicdev-10059 (music)/player-MediaRemote-DefaultPlayer
By default 21:27:08.115550+0800 mediaremoted Response: handlePlaybackQueueRequest<B0BDBB4E-C539-4D39-B51C-718115EBD7C4 assistantd-2659 /M/L/AF/R[0:1]> returned for origin-iPhone-1280262988/client-com.company.musicdev-10059 (music)/player-MediaRemote-DefaultPlayer in 0.0005 seconds
By default 21:27:08.119344+0800 assistantd Response: playbackQueue<B0BDBB4E-C539-4D39-B51C-718115EBD7C4 assistantd-2659 /M/L/AF/R[0:1]> returned <> for origin-iPhone-1280262988/client-com.company.musicdev-10059 (music)/player-MediaRemote-DefaultPlayer in 0.0010 seconds
By default 21:27:08.122322+0800 SpringBoard Response: playbackState<63A30582-E3C2-4F4D-AC57-8E5841FAD568> returned for origin-iPhone-1280262988/client-com.company.musicdev-10059 (music)/player-MediaRemote-DefaultPlayer in 0.0005 seconds
By default 21:27:08.126132+0800 chronod Observed com.company.musicdev stopped running for exempt reason: nowPlaying - remainingReasons: None By default 21:27:08.126285+0800 chronod [com.company.musicdev::com.company.musicdev.musicdesktopwidget:VisionWidget_medium4158108784:systemMedium:3758765227620768254:338.00/158.00/21.60:(null)~(null)] on local marked as requiring reload
By default 21:27:08.126455+0800 chronod [com.company.musicdev::com.company.musicdev.musicdesktopwidget:VisionWidget_medium4158108784:3758765227620768254] Reload with configuration [systemRequest(sessionEnded)-immediate-free-1] By default 21:27:08.126854+0800 mediaremoted Response: handlePlaybackQueueRequest<ACF764D9-05A6-41FF-8BB5-8CB81A8BC163 assistantd-2659 /M/L/AF/R[0:1]> returned for origin-iPhone-1280262988/client-com.company.musicdev-10059 (music)/player-MediaRemote-DefaultPlayer in 0.0008 seconds
By default 21:27:08.127960+0800 assistantd Response: playbackQueue<ACF764D9-05A6-41FF-8BB5-8CB81A8BC163 assistantd-2659 /M/L/AF/R[0:1]> returned <> for origin-iPhone-1280262988/client-com.company.musicdev-10059 (music)/player-MediaRemote-DefaultPlayer in 0.0016 seconds
By default 21:27:08.128091+0800 wifid Response: playbackState returned for origin-iPhone-1280262988/client-com.company.musicdev-10059 (music)/player-MediaRemote-DefaultPlayer in 0.0115 seconds
When the music state changes, you can see the widget is triggered to refresh. I want to ask if this is the system’s mechanism? I checked my code and there is no operation to actively refresh the widget when pausing or playing. Can this situation be avoided?
Hi,
I am setting up the iPadOS26 Menu Bar, and it comes with some existing menu items that don't make sense for my app. For example, under "File" menu, there are options for New Window, Duplicate, Move, Rename and Export that I would like to remove (which keeping the Close Window option).
What's the best way to do this?
Topic:
UI Frameworks
SubTopic:
UIKit
Hi,
When I have a UITextView displayed on screen and in focus, the iPad keyboard shows buttons to Bold, Italics and Underline text (since it supports attributed text), and also a 'formatting' button that allows the user to change the font, color and size of the text, as well as justify text and add numbered lists and bullet points.
Is there any way to disable or remove this 'formatting' button? My app doesn't support saving these options (other than bold, italics and underline), so it confuses users to see this option.
Thanks.
Topic:
UI Frameworks
SubTopic:
UIKit