While preparing automated screenshots with Xcode UI tests for the iOS 26 release, I noticed that this simple line of code
app.buttons["myTabItem"].tap()
doesn't always work, both on iPhone and iPad Simulator. In fact, it rarely works. Even when repeating the same test, mostly it fails on that line, but a few times it works and I can see the tab item change in the simulator.
My main view looks like this:
TabView {
MyTab1()
.tag(tag1)
.tabItem {
Label("label1", systemImage: "image1")
}
MyTab2()
.tag(tag2)
.tabItem {
Label("label2", systemImage: "image2")
.accessibilityIdentifier("myTabItem")
}
The error I get is
Failed to tap "myTabItem" Button: No matches found for Elements matching predicate '"myTabItem" IN identifiers' from input
In the given list of buttons, I see the tab items with their labels, but none of them seem to have an identifier, while other buttons have the correct identifier. I wonder how this can only sometimes work.
I tried isolating the issue by iteratively commenting out parts of the SwiftUI code, but unfortunately the behaviour seems erratic. When a change results in the issue not happening anymore, undoing the last X changes often causes the issue to stay away, even with configurations that previously had the issue. I've already spent almost a whole day trying to find the root cause, but with such apparently random behaviour it has proven impossible.
Of course, I cannot reproduce the issue with a fresh test project, so the only way to reproduce it with 95% probability is running my original project.
Has anyone had the same issue, or does anyone know how I could debug this to find out what causes my UI test to not be able to tap another tab item?
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
I'm using the simplified code below to create a window with 4 split view items, some of them collapsed. I would expect the title bar to be transparent since I'm using window.titlebarAppearsTransparent = true, but it seems that this particular view configuration causes the title bar to be visible until I collapse and expand the sidebar again.
Removing any of the split view items, uncollapsing any of them, or changing the view of any of the view controllers, causes the title bar to be consistently visible or hidden, although I don't understand the logic, since I'm telling the window that it should be transparent.
When launching the app in light mode, it's more difficult to notice the issue since the title bar background is equal to the content background and only the separator is visible (even though the code sets window.titlebarSeparatorStyle = .none):
After collapsing and expanding the sidebar, the separator is gone:
In dark mode the title bar is more visible:
After collapsing and expanding the sidebar, the title bar background and separator are gone:
I created FB20306872.
@main
class AppDelegate: NSObject, NSApplicationDelegate, NSToolbarDelegate {
var splitViewController: NSSplitViewController!
func applicationDidFinishLaunching(_ aNotification: Notification) {
let splitViewItem1 = NSSplitViewItem(sidebarWithViewController: ViewController1())
let splitViewItem2 = NSSplitViewItem(viewController: ViewController2())
let splitViewItem3 = NSSplitViewItem(viewController: NSViewController())
splitViewItem3.isCollapsed = true
let splitViewItem4 = NSSplitViewItem(viewController: NSViewController())
splitViewItem4.isCollapsed = true
splitViewController = NSSplitViewController()
splitViewController.splitViewItems = [splitViewItem1, splitViewItem2, splitViewItem3, splitViewItem4]
let window = NSWindow(contentViewController: splitViewController)
window.styleMask = [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView]
window.titlebarAppearsTransparent = true
let toolbar = NSToolbar(identifier: "")
toolbar.delegate = self
toolbar.displayMode = .iconOnly
window.toolbar = toolbar
window.titlebarSeparatorStyle = .none
window.makeKeyAndOrderFront(nil)
}
func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
return [.space, .flexibleSpace, .sidebarTrackingSeparator, .init("item")]
}
func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
return [.init("item"), .sidebarTrackingSeparator]
}
func toolbar(_ toolbar: NSToolbar, itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier, willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? {
switch itemIdentifier.rawValue {
case "item":
let item = NSToolbarItem(itemIdentifier: itemIdentifier)
item.image = NSImage(systemSymbolName: "sidebar.leading", accessibilityDescription: nil)
item.action = #selector(toggleSidebar(_:))
item.target = self
return item
default:
return nil
}
}
@objc func toggleSidebar(_ sender: Any?) {
splitViewController.splitViewItems[0].animator().isCollapsed = !splitViewController.splitViewItems[0].isCollapsed
}
}
class ViewController1: NSViewController {
override func loadView() {
view = NSView(frame: CGRect(x: 0, y: 0, width: 300, height: 200))
}
}
class ViewController2: NSViewController {
override func loadView() {
let textView = NSTextView()
let scrollView = NSScrollView(frame: CGRect(x: 0, y: 0, width: 400, height: 200))
scrollView.hasVerticalScroller = true
scrollView.documentView = textView
view = scrollView
}
}
When comparing the Assets.car file of the previous and current versions of my app, compiled with Xcode 16 and 26, respectively, with the Terminal command
assetutil --info MyApp.app/Contents/Resources/Assets.car
I see that the new version contains many more app icons at different sizes, increasing my app's size by 1 MB (not much, but considering that the app is only 6 MB in total...):
{
"AssetType" : "MultiSized Image",
"Name" : "AppIcon",
"NameIdentifier" : 6849,
"Scale" : 1,
"SHA1Digest" : "9D75F76992E9E9E5531A214A4AE282EBD381F7EB903024E00FB25EB42381CC45",
"SizeOnDisk" : 308,
"Sizes" : [
"16x16 index:1 idiom:universal",
"32x32 index:2 idiom:universal",
"64x64 index:3 idiom:universal",
"128x128 index:4 idiom:universal",
"256x256 index:5 idiom:universal",
"512x512 index:6 idiom:universal",
"1024x1024 index:7 idiom:universal"
]
}
The previous one allowed me to add only two sizes:
{
"AssetType" : "MultiSized Image",
"Name" : "AppIcon",
"NameIdentifier" : 6849,
"Scale" : 1,
"SHA1Digest" : "AC782A2FFF9A4B2D563EF64DF41A179583440560F8732A176A8376B31000368E",
"SizeOnDisk" : 248,
"Sizes" : [
"256x256 index:1 idiom:universal",
"512x512 index:2 idiom:universal"
]
}
Is there a way to only ship the strictly necessary app icons sizes while using Xcode 26 Icon Composer, or will all the sizes be required going forward?
It’s very frustrating when in a feedback I specify that I cannot reliably reproduce it and the feedback gets closed with the message “Since this issue cannot be reproduced, this report has been closed”, e.g. FB18985938. Is Apple not interested in hearing about issues that cannot be reliably reproduced? Many issues unfortunately depend on a variety of factors and it’s often impossible for third-party developers or users to figure out how to reliably reproduce them. Usually these kind of issues get addressed by e.g. adding more logging so that the next time it happens it's easier to find out what's causing it. Then the last part of the message “Please file a new report with a sysdiagnose if you encounter this issue again” sounds like I’m being teased, because what use is a new sysdiagnose if I still cannot reproduce it reliably? It will just be closed like the last one.
I created FB20595673 for this issue.
I regularly receive emails from my customers asking why my app, which copies files from a source folder to a destination folder, gives an error during the copy operation, usually when some kind of NAS is involved. I then ask if copying the same file works in the Finder and they usually say yes. Then it’s up to me to contact the NAS vendor and ask why their NAS doesn’t work correctly with the copyfile function which my app uses to copy files, and provide them with a sample Xcode project that reproduces the issue.
It would be so much easier for me, and probably other developers as well, if my customers could test their NAS with the Finder, then if it doesn’t work, contact their NAS vendor and solve the issue, or if it works, rest assured that file copies will work for any other app that uses the same API as the Finder. I could spend my time doing much more productive and interesting work rather than checking why every other NAS doesn’t work with my app which, after all, uses the most basic file copy mechanism available on macOS.
Is there any chance that in the future (hopefully sooner than later) there will be an API to copy files like the Finder with progress information, or is there a reason why this won't ever be possible?
I created FB20929181.
Here is the code:
UIView.setAnimationsEnabled(false)
let _ = textView.becomeFirstResponder()
UIView.setAnimationsEnabled(true)
Is there a way I can make the text view first responder without triggering an animation, so that I can set a custom scroll offset at the same time?
When tapping the Handoff icon of my app on the Mac or on the iPad, Xcode logs this error:
[default personal] [ERROR] +[NSURL(BRAdditions) br_documentURLFromBookmarkableString:error:]: (passed to caller) error: Error Domain=BRCloudDocsErrorDomain Code=8 "Not Entitled" UserInfo={NSDescription=Not Entitled}
When setting a breakpoint at NSApplicationDelegate.application(_:continue:restorationHandler:), I can see that userInfo.activityType is the one specified with the key NSUbiquitousDocumentUserActivityType under the Info.plist Document Types, but userActivity.userInfo is empty, so the document url is apparently not sent. Is there something else I have to set up?
I have a custom UITextView where entering text causes the undo button in the software keyboard to be enabled. When I override the undo manager like this:
class TextView: UITextView {
let _undoManager = UndoManager()
override var undoManager: UndoManager? {
return _undoManager
}
}
the auto-enabling of the undo button doesn't work anymore. What is the correct way of providing my own undo manager?
My app allows scanning any selected directory, but I noticed that even when I enable Full Disk Access in the System Preferences, when enumerating the contents of any of the subdirectories of another user's home folder (Documents, Downloads etc.) a permission error is returned. Even when running the app from the Terminal with sudo nothing changes. Using sudo du works. Is this a limitation of macOS apps?
Up until macOS 12, there was a checkbox labelled "Hide" for each login item in the Users & Groups System Preferences. Now in macOS 13 the login items have been moved to the General System Preferences, but the "Hide" checkbox has disappeared. Is there a way to know from within the app that it was launched as a login item, without offering an in-app "Launch at login" option which would allow me to control the whole process, but would be quite some effort to just replace that one little option?
The desired outcome of the code below is that both the red and yellow spheres should be at the same position at the center of the scene, (0, 0, 0), but instead the red sphere remains at its initial position (1, 0, 0). Commenting out any of the lines marked in the code, strangely, solves the issue. The code shows a simplified version of some other code, so it would be desirable to keep the order of the lines as they currently are. Am I doing something wrong?
class GameViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
let scene = SCNScene(named: "art.scnassets/ship.scn")!
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
scene.rootNode.addChildNode(cameraNode)
cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)
let lightNode = SCNNode()
lightNode.light = SCNLight()
lightNode.light!.type = .omni
lightNode.position = SCNVector3(x: 0, y: 10, z: 10)
scene.rootNode.addChildNode(lightNode)
let scnView = self.view as! SCNView
scnView.scene = scene
let parent0 = SCNNode()
scene.rootNode.addChildNode(parent0)
let parent1 = SCNNode()
scene.rootNode.addChildNode(parent1)
let sphere0 = SCNNode(geometry: SCNSphere(radius: 1))
sphere0.geometry!.firstMaterial!.diffuse.contents = NSColor.red
let sphere1 = SCNNode(geometry: SCNSphere(radius: 1))
sphere1.geometry!.firstMaterial!.diffuse.contents = NSColor.yellow
sphere0.position = SCNVector3(x: -1, y: 0, z: 0) // commenting out this line solves the issue
parent1.addChildNode(sphere0) // or commenting out this line solves the issue
sphere0.position = SCNVector3(x: 0, y: 0, z: 0)
parent0.addChildNode(sphere1) // or commenting out this line solves the issue
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
print(sphere0.worldPosition, sphere1.worldPosition)
}
}
}
I'm trying to adapt the Filter Network Traffic sample code found at https://developer.apple.com/documentation/networkextension/filtering_network_traffic
In FilterDataProvider.swift I've replaced the argument passed to NEFilterDataProvider.apply(_:completionHandler:) with nil, which according to the documentation should apply the default settings. Instead I'm getting the following error:
Error Domain=NEFilterErrorDomain Code=1 "The settings parameter doesn’t correspond to a NEFilterSettings object" (translated from my local language)
(When logging the error with os_log, the Console app just shows it as <private>. A NSLog call instead displays it correctly.)
After that the internet doesn't seem to work at all anymore and I have to trash the app to make the internet work again. (If the bin is not completely empty before trashing the app from the Applications folder, I'm prompted that there is another operation in progress like moving a file.)
If a nil parameter doesn't work, what is the correct way of not filtering anything, but just observing all the network traffic?
I'm using this code to get the path of an executable from the audit token provided in NEFilterDataProvider.handleNewFlow(_:):
private func securePathFromAuditToken(_ auditToken: Data) throws -> String? {
let secFlags = SecCSFlags()
var secCode: SecCode?
var status = SecCodeCopyGuestWithAttributes(nil, [kSecGuestAttributeAudit: auditToken] as CFDictionary, secFlags, &secCode)
guard let secCode = secCode else {
throw SecError(status)
}
var secStaticCode: SecStaticCode?
status = SecCodeCopyStaticCode(secCode, secFlags, &secStaticCode)
guard let secStaticCode = secStaticCode else {
throw SecError(status)
}
var dict: CFDictionary?
status = SecCodeCopySigningInformation(secStaticCode, secFlags, &dict)
guard let dict = dict as NSDictionary? else {
throw SecError(status)
}
if let identifier = dict[kSecCodeInfoIdentifier as String] as? String, let path = NSWorkspace.shared.urlForApplication(withBundleIdentifier: identifier)?.path {
return path
} else if let path = dict[kSecCodeInfoMainExecutable as String] as? String {
return path
}
return nil
}
But it seems that only applications inside the /Applications folder have a non-nil path. For all other executables I have to resort to this code, which I have read is not as secure:
private func insecurePathFromAuditToken(_ auditToken: Data) throws -> String? {
if auditToken.count == MemoryLayout<audit_token_t>.size {
let pid = auditToken.withUnsafeBytes { buffer in
audit_token_to_pid(buffer.baseAddress!.assumingMemoryBound(to: audit_token_t.self).pointee)
}
let pathbuf = UnsafeMutablePointer<Int8>.allocate(capacity: Int(PROC_PIDPATHINFO_SIZE))
defer {
pathbuf.deallocate()
}
let ret = proc_pidpath(pid, pathbuf, UInt32(PROC_PIDPATHINFO_SIZE))
if ret <= 0 {
throw NSError(domain: NSPOSIXErrorDomain, code: Int(errno))
}
return String(cString: pathbuf)
}
return nil
}
This seems to happen with both NEFilterFlow.sourceAppAuditToken and sourceProcessAuditToken. Is this expected? Can it really be that all executables that are not apps shipped with macOS are not signed?
In my UI test I'm trying to set different languages. I noticed that with right-to-left languages, such as Arabic, the UI is still aligned left-to-right. When I manually run the app with the scheme's language set to Arabic, the UI is correctly aligned right-to-left. Am I missing something?
let app = XCUIApplication()
app.launchArguments += ["-AppleLanguages", "(ar)"]
app.launch()
In my UI test I'm trying to force some user defaults. It seems that one can override them with code such as:
var app = XCUIApplication()
app.launchArguments += ["-myUserDefaultKey", "value"]
app.launch()
But I would like to replace the value of a default where the key contains whitespaces, such as the key created automatically when setting NSSplitView.autosaveName = "someSplitView", which is NSSplitView Subview Frames someSplitView. I tried escaping the whitespaces with NSSplitView\\ Subview\\ Frames\\ someSplitView and putting the key between single or double quotes, but nothing helped. Is this somehow possible?
Also, what would be the preferred way of temporarily removing a user default instead of overwriting it?