Construct and manage a graphical, event-driven user interface for your macOS app using AppKit.

AppKit Documentation

Post

Replies

Boosts

Views

Activity

How does AppIntent changes get reflected in macOS
I have a basic Xcode project where I am adding a swift file with the below AppIntent. This causes the AppIntent action to be added in the Shortcuts app in MacOS. I wanted to know how is this AppIntent directly be able to add the Intent action in the shortcuts app. I have checked the build setting in the Xcode project but I did not find anything being generated that could have caused this. Can someone help me understand what internally happens that causes the action to be added to the shortcuts app? import AppIntents import SwiftUI @available(macOS 13, *) struct TWIntent: AppIntent { static let title: LocalizedStringResource = "TWMeditationIntent" static var description = IntentDescription("try adding this sample action as your TW shortcut") static var parameterSummary: some ParameterSummary { Summary("Get information on \(\.$TWType)") } // we can have multiple parameter of diff types @Parameter(title: "TWType", description: "The type to get information on.") var TWType: String func perform() async throws -> some IntentResult & ReturnsValue<String> & ProvidesDialog { NSLog(AppDelegate.TAG + "Inside perform() in MeditationIntent") return .result(value: TWType, dialog: "Logged a 15 minute break.\(TWType)") } }
0
3
432
Apr ’24
CGEventTapCreateForPid fails to get event tap
My app uses CGEventTapCreateForPid to monitor keyboard events of a corresponding process. My app has already enabled the Accessibility permission, and AXIsProcessTrustedWithOptions returns true. However, CGEventTapCreateForPid returns null. What could be the problem? Does anyone know? I tested and found that if CGEventTapCreateForPid returns null, I can reset the Accessibility permission using tccutil reset Accessibility myapp_bundleid without restarting my app. But my app can still get the permission through AXIsProcessTrustedWithOptions
2
0
511
Apr ’24
MacOS: Hidden Windows cannot be fetched in NSApp
Hi, Using purely swift programatically (no storyboard), I'm able to create an NSWindow like so: var window = NSWindow (contentRect: pInstruction.GetFrame (), styleMask: [.miniaturizable, .closable, .resizable, .titled], backing: .buffered, defer: false) window.title = "Some Title" window.contentViewController = MyViewController () let windowidentifier = NSUserInterfaceItemIdentifier ("WinID1") window.identifier = windowidentifier window.makeKeyAndOrderFront(nil) This works fine and I can see a window on screen. Later, when I want to access the window I can use a utility method: static func GetWindow(_ pWindowID: NSUserInterfaceItemIdentifier) -> NSWindow? { let windows = NSApp.windows for window in windows { if window.identifier == pWindowID { return window } } return nil } // Then I can call this function like so: let windowidentifier = NSUserInterfaceItemIdentifier ("WinID1") let window = GetWindow (windowidentifier) This also works fine. However, if I do window.setIsVisible(false) or window.orderOut (nil) to temporarily hide the window, then NSApp.windows returns an empty array and I'm not able to find the window object and my Utility method "GetWindow ()" doesn't work. Any suggestions on how I can find hidden windows?
2
2
607
Apr ’24
Any way to use a SymbolEffect in an NSButton
Examples of using SymbolEffect in AppKit all seem to be in NSImageView, and look through APIs it seems that the only way to apply those effect animations outside of SwiftUI is indeed in an NSImageView. I have a NSStatusItem where I'm using an SF Symbol in the NSStatusBarButton title (subclass of NSButton) and was trying to figure out if there was a way to use a SymbolEffect there. If the image of an NSButton uses (used) an NSImageView under the hood, that used to hidden in the buttons cell. Seeing how cells seem to be inaccessible now, perhaps there isn't a NSImageView in there these days anyway. Can NSStatusBarButton titles be provided by a custom view, oh I'm guessing the deprecated view property is still operational, but if I'm trying to release to the Mac App Store, that as equally off-limits as an NSButtonCell would have been. Is there a non-deprecated way that will let me ship to the App Store?
1
2
781
Feb ’24
Mysterious error when using a WKWebView in an InputMethodKit app
I modified an InputMethodKit example (fairly recent one from github, compiled fine and worked as expected on my machine as it was) to create a window with a WKWebView and the window doesn't load. I know that loadView is getting called, but the window never appears after calling showWindow on the window controller and there is a mysterious error in the console: bootstrap_check_in(): (os/kern) unknown error code (44c) From googling this it seems App Sandbox related, but I think I have everything set up correctly (App Sandbox on with outgoing connections allowed) Totally stumped, any help or ideas would be appreciated Here's the relevant code: View controller import Foundation import WebKit import AppKit class InputWindowViewController: NSViewController, WKUIDelegate { var webView: WKWebView! override func loadView() { NSLog("LoadView") webView = WKWebView() self.view = webView webView.uiDelegate = self webView.needsDisplay = true } override func viewDidLoad() { super.viewDidLoad() webView.load(URLRequest(url: URL(string:"https://www.apple.com")!)) } } Window controller import AppKit import Foundation import WebKit class InputWindowController: NSWindowController { var controller: InputWindowViewController? override init(window: NSWindow?) { controller = nil super.init(window: window) } override func loadWindow() { self.window = NSWindow(contentViewController: controller!) } required init?(coder: NSCoder) { controller = nil super.init(coder: coder) } } AppDelegate import Cocoa import InputMethodKit import WebKit // Necessary to launch this app class NSManualApplication: NSApplication { private let appDelegate = AppDelegate() override init() { super.init() self.delegate = appDelegate } required init?(coder: NSCoder) { // No need for implementation fatalError("init(coder:) has not been implemented") } } @main class AppDelegate: NSResponder, NSApplicationDelegate { var server = IMKServer() var candidates = IMKCandidates() var inputWindowController = InputWindowController() func applicationDidFinishLaunching(_ notification: Notification) { // Insert code here to initialize your application server = IMKServer(name: Bundle.main.infoDictionary?["InputMethodConnectionName"] as? String, bundleIdentifier: Bundle.main.bundleIdentifier) inputWindowController = InputWindowController() inputWindowController.controller = InputWindowViewController() inputWindowController.loadWindow() inputWindowController.showWindow(self) candidates = IMKCandidates(server: server, panelType: kIMKSingleRowSteppingCandidatePanel, styleType: kIMKMain) NSLog("tried connection") } func applicationWillTerminate(_ notification: Notification) { // Insert code here to tear down your application } } This code is probably awful in a lot of other ways I don't realize, but I wanted to get a webview window up before I put a bunch of time into this thing XCode 13.4 MacoOS 12.7.4
1
0
589
Apr ’24
Open Recent menu stopped working in my doc-based Mac app
Recently, when I open a document in my app, it just adds a blank line to the Open Recent submenu. Attempting to select that line produces an error alert saying "The document “(null)” could not be opened. The file doesn’t exist." However, the document does appear in the global Recent Items menu. I tried rebooting. I'm not subclassing NSDocumentController or doing anything weird about opening files. Ideas? P.S. I tried logging in to a different account, and tried changing the bundle ID. Neither helped.
1
0
623
Apr ’24
Mac app, SwiftUI: Change Dock menu
Hello. I'm trying to change my SwiftUI Mac app icon's menu in the Dock, using the NSApplicationDelegate's applicationDockMenu(_ : ) function. However, it does not work: The delegate function is only called once, randomly after launch, and then never again, and it will not show any items in that menu I return. When I right-click the app in the Dock, only the macOS-supplied items are shown, and my App delegate function is not called. Here's the code I use inside my NSApplicationDelegate: func applicationDockMenu(_ sender: NSApplication) -> NSMenu? { let men = NSMenu() print("applicationDockMenu called") var it = NSMenuItem(title: "Test1", action: #selector(test(_:)), keyEquivalent: "") it.target = self men.addItem(it) it = NSMenuItem(title: "Test2", action: #selector(test(_:)), keyEquivalent: "") it.target = self men.addItem(it) return men } @objc func test(_ sender: NSMenuItem) { print("application dock menu custom item called") } Is there a SwiftUI modifier I should be using instead of the NSApp delegate method, or is this just not supported at this time in SwiftUI Mac apps? Thank you, - Matthias
2
1
1k
Mar ’24
FAULT: <NSRemoteView: 0x14665e360 com.apple.TextInputUI.xpc.CursorUIViewService TUICursorUIViewService> determined it was necessary to configure <TUINSWindow: 0x126706c70> to support remote view vibrancy
This message is logged in Xcode when I start editing a text field in my macOS app. This started appearing in Sonoma. This doesn't happen in Ventura (same Xcode project). Every text field in the app is affected, regardless of the window. What could be the cause of this?
2
3
2.0k
Dec ’23
NSMenuItem's custom view property returns wrong locationInWindow value on NSResponder's mouseExited method
After popping up a NSMenu a few times, NSResponder's mouseExited event is called even when the cursor is inside the tracking area, returning the main app window's max X value, which makes the mouseEntered/Exited methods unusable for tracking whether or not cursor is currently inside the view's frame. Steps Create a NSMenuItem with a custom view inside Add a tracking area to the views frame Add a background color that changes on mouseEntered/Exited Open and close NSMenu a few times until the color starts flickering when moving the cursor inside the view's frame If possible, print out NSEvent's locationInWindow on both mouseEntered and Exited and see that the location for exited method is not being reported correctly, while the flickering from the bg color being set is happening. Expected Result mouseExited should only be called the cursor leaves the tracking area. locationInWindow values should not exceed the NSPopUpWindow's frame. Tested on macOS Sonoma 14.3.1 and 14.4.1; Xcode 15.2; Feedback ID https://feedbackassistant.apple.com/feedback/13698735
0
1
589
Mar ’24
NSMenu's .sectionHeader/.separator items do not return a nil value on willHighlight method
Using NSMenuItem's delegate method menu(_ menu: NSMenu, willHighlight item: NSMenuItem?) should return a nil item when the mouse location is moved out of the NSMenu window or if any of the items should not be highlighted. As per Apple Developer website: Only one item per menu can be highlighted at a time. If item is nil, it means that all items in the menu are about to be unhighlighted. But, on macOS Sonoma, when moving the mouse over a .sectionHeader and/or a Separator item, willHighlight won't be called, which makes it not return any item (neither nil, nor the section header). This behavior makes it impossible to use willHighlight method to determine whether custom views should be highlighted or not. Is this a bug or expected behavior?
4
0
693
Mar ’24
NSMenu's submenu won't call willHighlight method for items using custom views
On a submenu (NSMenu), items that use custom views as part of their layout, do not call NSMenu's delegate willHighlight method. The method is called correctly when placing the same items with custom views inside the root/parent NSMenu. Steps Create a NSMenu with at least two NSMenuItem; One with a custom view and another without it. Add a submenu to the item without a custom view; make sure to set the submenu's delegate Add multiple items to the submenu; Make sure some of the items are using custom views Using one of NSMenu's delegate method, willHighlight, check if it will return an item when hovering over the custom view items inside the submenu Notice it will only return when hovering over items that do not use a custom view. Expected Result NSMenu's willHighlight method should be called and inform with item with custom view should be highlighted inside the submenu. Tests done on macOS 14.3.1 and 14.4.1. Xcode 15.2 and 15.3.
1
1
471
Mar ’24
UIPasteboard Item on MacOS is Not Expiring
Hello, When running an iPad app on Apple Silicon (M1) the expirationDate OptionKey of the UIPasteboard has no impact, i.e. the copied value is never removed from the clipboard. The following code works perfectly on iOS, however, behaves how I described above on macOS. let currentDate = Date() let expireDate = currentDate.addingTimeInterval(TimeInterval(90)) UIPasteboard.general.setItems([[UIPasteboard.typeAutomatic: myString]], options: [UIPasteboard.OptionsKey.expirationDate: expireDate]) Is this a bug? I am on Swift 5.10. Thank you!
1
0
443
Mar ’24
macos: find all installed applications capable of editing (eg) .jpg files
Hi, I think the title says it: my application needs to obtain a list of all applications that are configured as potential editors of a certain file type, for example jpeg or tiff. I've found LSCopyAllRoleHandlersForContentType which appears to do what I need, but it is deprecated since macos 12.0. What's the modern alternative? My app is built in c++ with some objective-c. Thanks Joost
1
0
509
Mar ’24
A Swift input method switcher works only after changing focus to another window
-1 I am trying to write a MacOS app which switch input methods by previously assigned shortcut(command+space in here). Switching input methods preoperly works so that the language icon at the status bar(top right) immediately changes as I put the shortcut. The problem I got in here is that the actual input method does not change. For example, if I run my app when the selected input method is Korean, then although the status bar is showing the selected input method is Japanese after command+space, what I can only type is Korean characters. However, after I change focus to another text app(e.g. from sublime text to xcode), only then the selected input method is reflected well. I am using MacOS Monterey 12.6 and Xcode 13.1. My project contains two source files. The code in the file AppDelegate.swift is as follows: import Cocoa @NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate { var switcher = Switcher() } And the code in the file Switcher.swift is as follows: import Cocoa import MASShortcut class Switcher{ var lang: Int = 0 var kr: TISInputSource? var jp: TISInputSource? var en: TISInputSource? init(){ let inputSourceNSArray = TISCreateInputSourceList(nil, false).takeRetainedValue() as NSArray let inputSourceList = inputSourceNSArray as! [TISInputSource] for inputSource in inputSourceList { if inputSource.id == "com.apple.inputmethod.Korean.2SetKorean" { self.kr = inputSource } if inputSource.id == "com.apple.inputmethod.Kotoeri.RomajiTyping.Japanese" { self.jp = inputSource } if inputSource.id == "com.apple.keylayout.ABC" { self.en = inputSource } } self.register() } func switchLang(){ self.lang = (self.lang + 1) % 3 switch lang { case 0: TISSelectInputSource(self.kr) case 1: TISSelectInputSource(self.jp) case 2: TISSelectInputSource(self.en) default: print("error") } } func register() { let langShortcut = MASShortcut(keyCode: kVK_Space, modifierFlags: [.command]) MASShortcutMonitor.shared()?.register(langShortcut, withAction: { self.switchLang() }) } } I wrote these codes by referring KAWA, but KAWA does not make this issue. I have analyzed all codes of KAWA several times, I couldn't find out why the same problem does not occur in KAWA. I am quite new to Swift, and I have no idea to approach. Could you help me....? Thank you.
0
0
550
Mar ’24
Need advice for closing subwindows when closing main document window
I have a document class that makes a main window for showing the data. Pieces of that data can be opened in separate subwindows for editing. When the user closes the main window and the document is dirty and the subwindows are dirty, I would like to present UI that asks the user if they want to save the changes in the subwindows (and possibly the main window if I decide to turn off autoSavesInPlace for the document). I've tried a number of possible methods of doing this, but always run into some roadblock: -Overriding shouldCloseWindowController:delegate:shouldCloseSelector:contextInfo: where I would go through the open subwindows and asking and tell them to do their own UI for asking if they should be saved. This is no good because everything returns back to the run loop and the doc would close, leaving the subwindows open with their Save? sheets up. -Making the subwindows inherit from NSEditor and registering them with the document. This looked like it would work, but it caused an infinite loop in my override of commitEditingWithDelegate:didCommitSelector:contextInfo: that I don't understand. I'm probably calling the didCommitSelector wrong because the docs aren't clear and provide no example. -Adding each subwindow's NSWindowController to the document's windowControllers list. I don't recall the problems this caused. Any sage advice about this? Possible examples? The Document is Swift, the subwindows are Cocoa, so examples in either language is fine.
1
0
507
Mar ’24
NSScrollView two finger drag being interrupted
I have a fairly robust MacOS application that has an NSScrollView that contains a canvas with various subviews (including web views and text views that contain scroll views), and a couple of peer views that track items in the scroll view (eg: screen space controls). Some of these views interrupt two finger scrolling. Every scroll view, and one of the peer views (essentially a stack view with buttons in it). I have written an additional bare bones application which does roughly the same thing, and my bare bones application works perfectly: Start two-finger dragging, scroll any of these other things under the cursor, I can continue to drag (and start dragging in any of those, and they drag without interfering with the parent scroll view). I have tried everything to recreate the interruption, including drag gestures attached to these various ancillary views, and I cannot figure out why dragging some of these views under the cursor interrupts two finger drag in our application, but not in my testbed. Does anyone have suggestions for how to debug this? I can see that there is a gesture recognizer in the NSScrollView hierarchy, but I don't see it in any of my gesture recognizer handling. I have breakpoints on every variation of hit testing and mouse motion, and none of them are getting hit in unexpected ways. I'm at my wit's end. Thanks.
0
0
395
Mar ’24
Mouse events on popup menu view seem to be incorrect in Sonoma.
as I open the pop-up menu and move the mouse before that opened, MouseEntered Event and MouseExited Event are called when mouse moved. The following trackingAreas options are inclued in the view in pop-up area. NSTrackingInVisibleRect, NSTrackingMouseEnteredAndExited, NSTrackingMouseMoved, NSTrackingActiveInKeyWindow LocationInWindow of MouseExitedEvent seem to be incorrect. This problems does not occur in the following cases. Do not move the mouse until the popup is fully opened. Left mouse button down on pop-up area. Move the mouse out of the pop-up area. This issue occurs in Sonoma(MacOS14.0) and later. I would like to know if this is a code issue or a bug in the OS Version. AppDelegate.h #import &lt;Cocoa/Cocoa.h&gt; @interface ViewInPopup : NSView { NSString* resultStr; NSUInteger enteredCount; NSPoint lastEnteredPos; NSUInteger exitedCount; NSPoint lastExitedPos; NSUInteger movedCount; NSPoint lastMovedPos; NSTrackingArea* trackingArea; } @end @interface AppDelegate : NSObject &lt;NSApplicationDelegate&gt; { NSMenu* myMenu; ViewInPopup* viewInPopup; } - (IBAction)onClickButton:(id)sender; @end AppDelegate.mm #import "AppDelegate.h" @interface ViewInPopup () - (void)showResult:(NSEvent*)event; @end @implementation ViewInPopup - (id)initWithFrame:(NSRect)frameRect { self = [super initWithFrame:frameRect]; [self setWantsLayer:TRUE]; [[self layer] setBackgroundColor:[NSColor redColor].CGColor]; return self; } - (void)drawRect:(NSRect)dirtyRect { [super drawRect:dirtyRect]; [resultStr drawInRect:[self bounds] withAttributes:nil]; } - (void)updateTrackingAreas { if (trackingArea) { [self removeTrackingArea:trackingArea]; } NSTrackingAreaOptions options = NSTrackingInVisibleRect | NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingActiveInKeyWindow; trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds] options:options owner:self userInfo:nil]; [self addTrackingArea:trackingArea]; [super updateTrackingAreas]; } - (void)mouseEntered:(NSEvent *)event { [self showResult:event]; [super mouseEntered:event]; } - (void)mouseExited:(NSEvent *)event { [self showResult:event]; [super mouseExited:event]; } - (void)mouseMoved:(NSEvent *)event { [self showResult:event]; [super mouseMoved:event]; } - (void)showResult:(NSEvent*)event { NSString* eventTypeStr = @""; switch (event.type) { case NSEventTypeMouseEntered: eventTypeStr = @"Entered"; [[self layer] setBackgroundColor:[NSColor redColor].CGColor]; if (enteredCount &gt;= NSUIntegerMax) { enteredCount = 0; } else { enteredCount++; } lastEnteredPos = event.locationInWindow; break; case NSEventTypeMouseExited: eventTypeStr = @"Exited"; [[self layer] setBackgroundColor:[NSColor blueColor].CGColor]; if (exitedCount &gt;= NSUIntegerMax) { exitedCount = 0; } else { exitedCount++; } lastExitedPos = event.locationInWindow; break; case NSEventTypeMouseMoved: eventTypeStr = @"Moved"; [[self layer] setBackgroundColor:[NSColor greenColor].CGColor]; if (movedCount &gt;= NSUIntegerMax) { movedCount = 0; } else { movedCount++; } lastMovedPos = event.locationInWindow; break; default: return; } resultStr = [NSString stringWithFormat:@"LastEventType:%@\n\nEnteredCount:%ld\nLastEnteredPosition:(%f, %f)\n\nExitedCount:%ld\nLastExitedPosition:(%f %f)\n\nMovedCount:%ld\nLastMovedPosition:(%f, %f)", eventTypeStr, enteredCount, lastEnteredPos.x, lastEnteredPos.y, exitedCount, lastExitedPos.x, lastExitedPos.y, movedCount, lastMovedPos.x, lastMovedPos.y]; [self setNeedsDisplay:YES]; } @end @interface AppDelegate () @property (strong) IBOutlet NSWindow *window; @end @implementation AppDelegate - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { // Insert code here to initialize your application myMenu = [[NSMenu alloc] init]; NSMenuItem* item = [[NSMenuItem alloc] init]; [myMenu addItem:item]; viewInPopup = [[ViewInPopup alloc] initWithFrame:NSMakeRect(0, 0, 300, 300)]; [item setView:viewInPopup]; } - (void)applicationWillTerminate:(NSNotification *)aNotification { // Insert code here to tear down your application } - (BOOL)applicationSupportsSecureRestorableState:(NSApplication *)app { return YES; } - (IBAction)onClickButton:(id)sender { [myMenu popUpMenuPositioningItem:nil atLocation:NSZeroPoint inView:(NSView*)sender]; } @end
2
1
1.1k
Oct ’23