Looking for help identifying the following ui element or 'widget' in this app, the window is a sort of 'drop zone', you drag and drop files to it, it then displays the DnD'd files as a 'file stack' which is a ui element commonly seen in the Dock. Unable to find the api to create this. Surely it exists? (A screenshot is attached)
AppKit
RSS for tagConstruct and manage a graphical, event-driven user interface for your macOS app using AppKit.
Post
Replies
Boosts
Views
Activity
Hello.
I could wrong, but it seems NSWorkspace.open cannot open xcodeproj.
When I try to do so in my sandboxed App, the App would hang the thread, causing NSWorkspace.open not responsive in the following calls. If called on the @main thread, then bad luck, it would cause dead lock.
Callings this function on a normal file, such as .txt, or in a Command line Tool works perfectly. Is there anything obvious that I missed?
I have permissions to read/write the files, as indicated by url.resourceValues(forKeys: [.isWritableKey]).isWritable.
In my app I use NSMenu.popUp(positioning:at:in:) for displaying a menu in response to the user clicking a button.
But it seems that when the menu is opened inside a modal window, all the menu items are always disabled.
Using NSMenu.popUpContextMenu(_:with:for:) instead works. What's the reason and what's the difference between the two methods? According to the documentation, one is for opening "popup menus" and the other for opening "context menus", but I cannot see an explanation of the difference between the two.
@main
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ aNotification: Notification) {
let window = NSWindow(contentViewController: ViewController())
NSApp.runModal(for: window)
}
}
class ViewController: NSViewController {
override func loadView() {
let button = NSButton(title: "Click", target: self, action: #selector(click(_:)))
view = NSView(frame: CGRect(x: 0, y: 0, width: 400, height: 400))
view.addSubview(button)
}
@objc func click(_ sender: Any?) {
let menu = NSMenu(title: "")
menu.addItem(withTitle: "asdf", action: #selector(asdf(_:)), keyEquivalent: "")
menu.addItem(withTitle: "bla", action: nil, keyEquivalent: "")
menu.items[0].target = self
menu.items[1].target = self
// NSMenu.popUpContextMenu(menu, with: NSApp.currentEvent!, for: view) // this works
menu.popUp(positioning: nil, at: .zero, in: view) // this doesn't work
}
@IBAction func asdf(_ sender: Any) {
print(0)
}
}
I'm displaying file structure using DisclosureGroup.
And I encountered a memory leak problem.
Code
Node
Node represents a file or a folder.
isExpanded is used to indicate if the child nodes are visible.
If true, it will find its child nodes, which are set into children.
If false, it will clear children for releasing references.
class Node: ObservableObject, Identifiable, Hashable, CustomStringConvertible {
// ...
@Published var name: String
@Published var children: [Node]?
@Published var isExpanded = false {
willSet {
if self.isFile {
// This node represents a file.
// It does not have any children.
return
}
if newValue {
if children?.count == 0 {
DispatchQueue.main.async {
// get child nodes
self.children = childrenOf(self.url)
}
}
} else {
if children?.count != 0 {
DispatchQueue.main.async {
// collapse child nodes
self.children?.forEach { child in
child.isExpanded = false
}
// clear children when this node is collapsed
self.children = []
}
}
}
}
}
init(/*...*/) {
// ...
print("init \(name)")
}
deinit {
// ...
print("deinit \(name)")
}
// ...
}
For convenience, I print some messages when initializing Node and deinitializing Node.
TreeNode
TreeNode displays Node using DisclosureGroup.
struct TreeNode: View {
@ObservedObject var parent: Node
@ObservedObject var node: Node
var body: some View {
if node.isFile {
Text(node.name)
} else {
DisclosureGroup(
isExpanded: $node.isExpanded,
content: {
if node.isExpanded {
ForEach(node.children ?? []) { child in
TreeNode(parent: node, node: child)
}
}
},
label: {
FolderNodeView(node: node)
}
)
}
}
}
struct FolderNodeView: View {
@ObservedObject var node: Node
var body: some View {
Label(
title: { Text(node.name) },
icon: { Image(systemName: "folder.fill") }
)
}
}
I use if node.isExpanded for lazy loading.
When node.isExpanded is true, it will show node's children and print initialization messages. Otherwise, it will hide child nodes and print deinitialization messages.
But unexpectedly it does not print any deinitialization messages when the node is collapsed. This indicates that it retains references and therefore these Node objects still exists in memory causing memory leak.
Demo
When the node is expanded, its child nodes will be displayed after loading is completed. The code works correctly.
Then I collapsed the node, it didn't print any deinitialization messages. And when I expanded it again, it initialized new nodes and deinitialized the old nodes at this time. Deinitialization seems to be delayed.
So I guess TreeNode retains references when content is hidden.
Then I deleted TreeNode in ForEach.
DisclosureGroup(
isExpanded: $node.isExpanded,
content: {
if node.isExpanded {
ForEach(node.children ?? []) { child in
// TreeNode(parent: node, node: child)
}
}
},
label: {
FolderNodeView(node: node)
}
)
It cannot display the child nodes. But it released reference correctly.
So the code works expectedly.
After that, I tried to replace TreeNode with Text or Label.
I found that none of them released references immediately when I collapsed the node.
Why did this happen?
Any idea how to fix it?
I am new to Apple 🍎 Development 👨💻 and Apple 🍎 Developer 👨💻 Forums.
I have not joined the Apple 🍎 Developer 👨💻 Program yet.
Is there any documentation 📖 that is only available to paid 💰 Apple 🍎 Developer 👨💻 Program members or is all of it freely available to those not (or not yet) in the paid 🚫💰 program?
Is Xcode freely downloadable or does it require it be purchased like it used to be for non-program members?
Hi folks,
In my macOS app I’m using NSColorPanel to present color picking options to the user. Therefore I’m attaching various custom NSColorLists before showing the color panel. The panel is always presented with the „Apple“ color list active, and I found no method to select a different color list. In my app I could determine the most relevant color list and would like to preselect it instead of relying on a manual selection by the user.
Is there any option to control the selected / active NSColorList of an NSColorPanel?
Additionally - but that more a minor topic and probably a candidate for a bug report: Since some major macOS versions (maybe starting with macOS 13 „Ventura“?) the order of NSColorLists in the default NSColorPanel is random. In the past color palettes were listed in reverse order of their attachments via „attachColorList:“.
Is there any way to control the order color palettes are listed by an NSColorPanel
I just spent one of my TSIs for this question - as my Apple developer membership is renewed shortly - but maybe this community as some smart tip to share...
Appreciate any help, Mattes
I have used this function and found that it doesn't activate the application synchronously because sometimes this function completes before any of the activated application windows get focused.
Documentation - https://developer.apple.com/documentation/appkit/nsrunningapplication/1528725-activatewithoptions
Hi,
Inside a Mac Catalyst app, I need to display a popover starting from an NSToolbarItem contained inside the app toolbar (like the Apple Maps Mac app does, see below image).
In order to do that, when I press the button I need to find the toolbar item view and use it as popover anchor.
How can I find the view or frame of an NSToolbarItem on Mac Catalyst?
A property that could help me is the NSToolbarItem "view" property (NSView), but that property has been marked has unavailable in Mac Catalyst.
Any idea?
Thank you
I’ve finally changed my main development platform to macOS 14 Sonoma and almost immediately have I encountered something I consider being a bug. I searched for similar issues, but nowhere have I found any relevant information or help.
The issue is rather funny; if you have a subview and, for whatever reason, it finds itself outside of its superview’s bounds, it remains visible, instead of being hidden. It’s like you have a window on your room wall, but still the interior of your room is visible outside of window’s borders :-)
Here’s a simple Xcode project that explains what I’m talking about:
https://zigz.ag/temp/SubviewBug/UnhiddenXcodeProject.zip
Unpack and build this project, run the test application and see it yourself.
However, there are some differences, regarding the Xcode/SDK version used to build the application and the macOS version it runs on. The project format is “Xcode 13.0” and MACOSX_DEPLOYMENT_TARGET = 13.0. Here you can find application bundle, build with Xcode 14:
https://zigz.ag/temp/SubviewBug/UnhiddenXcode14Build.zip
The relevant build parameters, as found in application's Info.plist are:
BuildMachineOSBuild: 22G605
DTPlatformVersion: 13.3
DTSDKBuild: 22E245
DTXcode: 1431
DTXcodeBuild: 14E300c
If you run it on both Ventura and Sonoma, you’ll see ti behaves as expected. However, here you can find application bundle, build with Xcode 15:
https://zigz.ag/temp/SubviewBug/UnhiddenXcode15Build.zip
The relevant build parameters, as found in application's Info.plist are:
BuildMachineOSBuild: 23D56
DTPlatformVersion: 14.2
DTSDKBuild: 23C53
DTXcode: 1520
DTXcodeBuild: 15C500b
Now, if you run this build on Ventura, you’ll see it behaves fine. Running it on Sonoma however, shows the behaviour I’m trying to explain; the ratio button titled “Two” remains visible, even though its superview shrinks and it goes out of its superview’s bounds. So, the issue is present only on Sonoma, if build with Xcode 15.
The difference is visible even inside Interface Builder. Here is a short video of shrinking a superview in IB of Xcode 14, note how the “Two” radio button becomes invisible, as it goes outside of its superview’s bounds:
https://zigz.ag/temp/SubviewBug/InterfaceBuilderXcode14.mov
Here is the video of shrinking the same superview in IB of Xcode 15, the “Two” radio button remains visible regardless of its superview’s bounds:
https://zigz.ag/temp/SubviewBug/InterfaceBuilderXcode15.mov
Is this a bug? Or did I miss something in macOS 14 Sonoma SDK release notes, which would indicate from now on this is expected behaviour (highly unlikely)?
-- Dragan
This might sound strange and but I'd really like to get this resolved.
I first though this was the fault of a macos application that I developed. But later I noticed that it is practically applies to every application on the macbook I've got.
If I press "Help" in the menu-bar, in any app on my mac. That app crashes.
In some apps, it crashes directly, in some, it show a corrupt list first, then crashes. This is how it looks in Safari for example (1 second after pressing "Help"):
Here's the stacktrace for Safari:
0 libobjc.A.dylib 0x181319c20 objc_msgSend + 32
1 Shortcut 0x1bd7aca5c -[SCTSearchManager hasNoResults] + 56
2 Shortcut 0x1bd7aea78 -[SCTSearchManager selectRowAfterTargetingItem:withMenu:] + 36
3 Shortcut 0x1bd7abdc4 SCTHelpMenuHandler + 508
4 HIToolbox 0x18afbb3a4 DispatchEventToHandlers(EventTargetRec*, OpaqueEventRef*, HandlerCallRec*) + 1092
5 HIToolbox 0x18afba828 SendEventToEventTargetInternal(OpaqueEventRef*, OpaqueEventTargetRef*, HandlerCallRec*) + 356
6 HIToolbox 0x18afba6b8 SendEventToEventTargetWithOptions + 44
7 HIToolbox 0x18b188878 SendItemEvent(MenuSelectData*, unsigned int, MenuData*, unsigned short) + 308
8 HIToolbox 0x18b050f10 UpdateMenuViewFocus(MenuSelectData*, MenuData*, short, short) + 568
9 HIToolbox 0x18b04be28 ViewFocusHandler(OpaqueEventHandlerCallRef*, OpaqueEventRef*, void*) + 520
10 HIToolbox 0x18afbb3a4 DispatchEventToHandlers(EventTargetRec*, OpaqueEventRef*, HandlerCallRec*) + 1092
11 HIToolbox 0x18afba828 SendEventToEventTargetInternal(OpaqueEventRef*, OpaqueEventTargetRef*, HandlerCallRec*) + 356
12 HIToolbox 0x18afba6b8 SendEventToEventTargetWithOptions + 44
13 HIToolbox 0x18b02f528 HIView::SendSetFocusPart(short, unsigned char, unsigned char, short*) + 248
14 HIToolbox 0x18b02f394 HIView::SetFocusPartInternal(short, unsigned char, unsigned char, short*, short, unsigned char, unsigned char) + 116
15 HIToolbox 0x18b02f14c HIView::SetFocusPart(short, unsigned char, unsigned char, unsigned int, FocusData*) + 240
16 HIToolbox 0x18b02ef90 HIViewSetFocus + 168
17 HIToolbox 0x18b05049c ChooseItem(MenuSelectData*, Rect const*) + 220
18 HIToolbox 0x18b1876e4 TrackMenuCommon(MenuSelectData&, unsigned char*, SelectionData*, MenuResult*, MenuResult*) + 800
19 HIToolbox 0x18b052c0c MenuSelectCore(MenuData*, Point, double, unsigned int, OpaqueMenuRef**, unsigned short*) + 348
20 HIToolbox 0x18b052a00 _HandleMenuSelection2 + 416
21 AppKit 0x184b09918 _NSHandleCarbonMenuEvent + 256
22 AppKit 0x184b0973c _DPSEventHandledByCarbon + 60
23 AppKit 0x1849b7104 -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 2232
24 Safari 0x1ac42a218 -[BrowserApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 228
25 AppKit 0x1849aaf7c -[NSApplication run] + 464
26 AppKit 0x1849823cc NSApplicationMain + 880
27 Safari 0x1ac791e24 SafariMain + 408
28 dyld 0x18135bf28 start + 2236
This is a problem that only exists on MacOS 13 (Ventura) and MacOS 14 (Sonoma). On all earlier versions of MacOS, the existing code works well, and has for many years.
I am working on an long-running Objective-C MacOS app (non-sandboxed) that uses WKWebView to display a static web page within a "pane" of a larger NSView. By "pane", I mean the WKWebView might be the only view within the encompassing NSView (thereby occupying all of its space), or it might occupy only one rectangle within it, if the NSView is divided into arbitrary rectangles.
(Whether or not the WKWebView takes up the entire surrounding rectangle, or just a section of it, seems irrelevant.)
The WKWebView is created offscreen at startup time, and later may become visible under user control. I don't need the displayed web page to permit any interactivity with the user other than scrolling, and I disable Javascript on the page using the WKWebViewConfiguration - which appears to work as intended.
I therefore have no need for NSTrackingArea either, and am not using it. It does appear that the WKWebView has one NSTrackingArea by default, but it's not mine. I can remove it programmatically, but that does not appear to make any difference.
When the WKWebView is visible, the app will instantly crash as soon as the cursor enters its rectangle.
The stack trace shows the error:
[_NSTrackingAreaCGViewHelper cursorAreas]: unrecognized selector sent to instance
The problem here is that the _NSTrackingAreaCGViewHelper method appears to be something within an Apple internal framework - I can't find discussion of it anywhere on the Internet, or in Apple's developer docs. Same for the selector "cursorAreas" - I can't find any information about it at all.
So this is starting to feel like a bug somewhere in Apple's internal framework. I can't understand why it's crashing with a message related to NSTrackingArea (or similar objects), when I'm not using tracking at all, but the "unrecognized selector" error is even more disturbing - I'm not calling the method, and certainly can't control the selector. I can't be sure, but this feels like Apple's error.
I'd like to know if there might be a way for me to configure WKWebView to not use tracking at all, thereby eliminating the issue entirely, but I can't find a way to do that other than removing the NSTrackingAreas from the WKWebView, but that's not helping either.
Can anyone (especially from Apple) offer any guidance? If it's an Apple bug, I would love to know how to work around it - it's a show-stopper for this app.
Thanks in advance...
Is it possible that I bypass tableView.makeView so that I can create a NSTableCellView on the fly (based on some logics)?
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
if NSTableColumn.identifier.rawValue == "labelColumn" {
let myCellView = NSTableCellView()
myCellView.textField.strinValue = "label text"
return myCellView
} else {
let complexView = loadFromNib() // of NSTableCellView
// populate complexView
return complexView
}
}
Hi all,
I've been playing around with making a screen saver using ScreenSaver.framework and having issues with (what appears to be) macOS caching the previous version of the screensaver until I reboot.
I have written a screen saver that works, however if I make some changes to the code, re-archive and reinstall the newly compiled screen saver still presents the old screen saver. I've tried incrementing the build number to no avail.
Does anyone have a solution to this?
My workflow :-
Uninstall and delete all instances of my screen saver.
Reboot
Open Xcode, compile, re-archive my screen saver.
Double-click the archived screen-saver, click to install for this user.
Test screensaver -- success!
Now,
Delete the screensaver by right-click on screensaver in System Settings, "Delete "
Make changes to my code, rearchive.
Double-click the archived screen-saver, click to install for this user.
Test screensaver -- fail! Still shows the old version of the screensaver.
Reboot machine
Test screensaver -- success! Screensaver now shows the changes I made.
Many thanks all.
I've created a custom NSCollectionView layout that is vertical in design and it supports dragging and dropping. However, the drawn drop indicator only is a vertical line in the middle of the inter gap or drop zones specified. Ideally, I'd like for this line to be horizontal, extending the width of the frame rather than the vertical and extending the height. Basically, I am trying to replicate the drop indicator that's used in NSTableView or NSOutlineView.
Is there any way to accomplish this?
I have a view (custom subclass of NSView) that overrides mouseDown: and mouseUp:. If I double-click the view, I expect to see a sequence of events:
mouseDown with clickCount == 1
mouseUp with clickCount == 1
mouseDown with clickCount == 2
mouseUp with clickCount == 2
Usually, that's what happens. But occasionally, the second or both mouse up events don't arrive. That's a problem, because it's my understanding that if you want to handle a double-click, you should be looking for the second mouse up. I am certain that the mouse location is always within the bounds of the view. What could cause this? (Testing on macOS 13.6.4.)
Added: I use a subclass of NSApplication, and override nextEventMatchingMask:untilDate:inMode:dequeue: and sendEvent:. The overrides usually just call through to the superclass method. Logging mouse events from these methods, I see that in the problematic cases, the mouse up events are received from the queue, but never sent.
There's WKWebView.find() method that highlights search result within a WKWebView element on macOS but I don't see any way to clear this highlight. When I search for an empty string is does nothing and the latest search result remains highlighted.
How do we open Keyboard Viewer programatically? I am working on Sonoma Mac Application.
I could open "Emoji & Symbols" programatically as follows.
NSArray *sources = (__bridge NSArray*)TISCreateInputSourceList(nil, false);
TISInputSourceRef keyboardViewer = (__bridge TISInputSourceRef)[sources objectAtIndex: 2]; // "Emoji & Symbols" is the 3rd one. So 2.
TISSelectInputSource(keyboardViewer);
CFRelease((CFTypeRef)sources);
After some searching, Keyboard Viewer could be opened with similiar approach with above in the old previous version of MacOS.
I have a strong feeling there is a way to bring up the keyboard because we can bring up "Emoji & Symbols". I mean, why would apple prevent us to show Keyboard Viewer.
Any idea?
Hello,
I am trying to simulate a keystroke inside a macOS application.
Here is what i've done:
let src = CGEventSource(stateID: CGEventSourceStateID.hidSystemState)
let cmd_down = CGEvent(keyboardEventSource: src, virtualKey: 0x38, keyDown: true)
let cmd_up = CGEvent(keyboardEventSource: src, virtualKey: 0x38, keyDown: false)
cmd_down?.post(tap: .cghidEventTap)
cmd_up?.post(tap: .cghidEventTap)
macOS is asking me to allow my application on TCC accessibility. This is a global privilege and needs admin rights.
And i want to avoid that.
Is there an alternative to simulate a key stroke inside my application ?
Thanks
I have a table view where each row has two labels, one left-aligned and one right-aligned. I would like to reload a single row, but doing so causes the right-aligned label to hug the left-aligned label.
Before the reload:
After the reload:
Reloading the whole table view instead, or disabling automatic row height, solves the issue. Can a single row be reloaded without resorting to these two workaround?
class ViewController: NSViewController, NSTableViewDataSource, NSTableViewDelegate {
override func loadView() {
let tableView = NSTableView()
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.dataSource = self
tableView.delegate = self
tableView.usesAutomaticRowHeights = true
let column = NSTableColumn()
column.width = 400
tableView.addTableColumn(column)
let scrollView = NSScrollView(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.documentView = tableView
view = scrollView
Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { _ in
print("reload")
tableView.reloadData(forRowIndexes: IndexSet(integer: 2), columnIndexes: IndexSet(integer: 0))
// tableView.reloadData()
}
}
func numberOfRows(in tableView: NSTableView) -> Int {
return 5
}
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
let cell = NSTableCellView()
let textField1 = NSTextField(labelWithString: "hello")
textField1.translatesAutoresizingMaskIntoConstraints = false
let textField2 = NSTextField(wrappingLabelWithString: "world")
textField2.translatesAutoresizingMaskIntoConstraints = false
textField2.alignment = .right
let stack = NSStackView(views: [
textField1,
textField2
])
stack.translatesAutoresizingMaskIntoConstraints = false
stack.distribution = .fill
cell.addSubview(stack)
NSLayoutConstraint.activate([stack.topAnchor.constraint(equalTo: cell.topAnchor, constant: 0), stack.leadingAnchor.constraint(equalTo: cell.leadingAnchor, constant: 0), stack.bottomAnchor.constraint(equalTo: cell.bottomAnchor, constant: 0), stack.trailingAnchor.constraint(equalTo: cell.trailingAnchor, constant: 0)])
return cell
}
}
Hello,
I am developing a multi-platform app, and I need an emoji picker. It should be the same as the emoji selection view in the Reminders App.
Reminders App Image:
(A button; when pressed calls the MacOS emoji selector, and the emoji selected is linked to a variable).
I know you can call the EmojiSelector with
NSApp.orderFrontCharacterPalette($variable)
However, it only records the variable if you have a working text field linked to the variable. Then, if you edit the text field you can select more than 1 character, a non-emoji, and the emoji popover is not shown under the button.
How do I make an emoji selector like the one above. Does it require a textfield for the selected emoji to be linked to a variable.
If it does, can the text field be:
Not Viewable and in a ZStack under the button
Only editable by the emoji selector
Replace the current emoji when another is selected
Sorry if my question is lengthy. I have everything else in my app ready, and want to release it to the app store (it will be free).
Thank you for any help,
Dev_Pro