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

Posts under AppKit tag

200 Posts

Post

Replies

Boosts

Views

Activity

Detecting marked range in UI/NSTextViews at the time of shouldChangeTextIn
We have submitted a feedback for this issue: FB21230723 We're building a note-taking app for iOS and macOS that uses both UITextView and NSTextView. When performing text input that involves a marked range (such as Japanese input) in a UITextView or NSTextView with a UITextViewDelegate or NSTextViewDelegate set, the text view's marked range (markedTextRange / markedRange()) has not yet been updated at the moment when shouldChangeTextIn is invoked. UITextViewDelegate.textView(_:shouldChangeTextIn:replacementText:) NSTextViewDelegate.textView(_:shouldChangeTextIn:replacementString:) The current behavior is this when entering text in Japanese: (same for NSTextView) func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { print(textView.markedTextRange != nil) // prints out false DispatchQueue.main.async { print(textView.markedTextRange != nil) // prints out true } } However, we need the value of markedTextRange right away in order to determine whether to return true or false from this method. Is there any workaround for this issue?
6
0
1.2k
Jan ’26
Changing the menu bar display name
Hello, I'm currently working on an app that will have a different name (and UI) depending on an environment variable that is set by that app's custom installer that I also wrote. I'm trying to change the app name that is displayed in the menu bar (top left) programmatically. I've done some research and found that it's probably not possible to do so because it's fetched from the app's Info.plist The answer is probably already there but I'll ask the question: Is it possible to change the app's name in the menu bar without tampering with the Info.plist (as it will break the signature at runtime, and it can't be done at compile time) The use case here is that I'm shipping a single app with multiple installers, because the app will be the same for all sets of users but it will have minor UI changes (which in my opinion, don't need an entire separate release), the installers will set a flag that the app will, based on, change its UI to the corresponding set of users. For the most part it's been successful but only small issue remain like this one. The reason it's done like that is when updating I'll ship 1 release for all users to update rather than having to ship multiple releases with no difference between them
1
0
1.2k
Jan ’26
NSPathControl -setURL: crash on macOS Tahoe
I received the following crash: Thread 0 Crashed: libsystem_kernel.dylib __pthread_kill + 8 libsystem_pthread.dylib pthread_kill + 296 (pthread.c:1721) libsystem_c.dylib abort + 124 (abort.c:122) libc++abi.dylib __abort_message + 132 (abort_message.cpp:66) libc++abi.dylib demangling_terminate_handler() + 304 (cxa_default_handlers.cpp:76) libobjc.A.dylib _objc_terminate() + 156 (objc-exception.mm:496) libc++abi.dylib std::__terminate(void (*)()) + 16 (cxa_handlers.cpp:59) libc++abi.dylib __cxxabiv1::failed_throw(__cxxabiv1::__cxa_exception*) + 88 (cxa_exception.cpp:152) libc++abi.dylib __cxa_throw + 92 (cxa_exception.cpp:299) libobjc.A.dylib objc_exception_throw + 448 (objc-exception.mm:385) Foundation -[NSConcreteMutableAttributedString initWithString:] + 268 (NSAttributedString.m:1049) CloudDocs -[BRCloudPathComponentDisplayMetadata initWithDisplayName:suffix:url:icon:] + 180 (BRCloudPathComponentDisplayMetadata.m:75) CloudDocs -[NSURL(BRCloudPathComponent) br_pathComponentDisplayMetadataWithOptions:]_block_invoke + 516 (BRCloudPathComponentDisplayMetadata.m:292) CloudDocs -[NSArray(BRAdditions) br_transform:keepNull:] + 228 (NSArray+BRAdditions.m:20) CloudDocs -[NSURL(BRCloudPathComponent) br_pathComponentDisplayMetadataWithOptions:] + 76 (BRCloudPathComponentDisplayMetadata.m:276) AppKit -[NSPathCell _autoUpdateCellContents] + 2080 (NSPathCell.m:442) AppKit -[NSPathCell setURL:] + 76 (NSPathCell.m:599) AppKit -[NSPathControl setURL:] + 64 (NSPathControl.m:366) I tried reproducing on my end by passing various URLs in iCloud Drive to an NSPathControl, file reference urls, attempting to evict a URL from iCloud Drive then settings the URL property without luck. Setting the URL to nil does not crash (the property is nullable). I have no idea how to trigger that code path. Anyone else run into this and have a workaround?
2
0
1.1k
Jan ’26
Why does NSEvent.addGlobalMonitorForEvents still work in a Sandboxed macOS app
I am building a macOS utility using SwiftUI and Swift that records and displays keyboard shortcuts (like Cmd+C, Cmd+V) in the UI. To achieve this, I am using NSEvent.addGlobalMonitorForEvents(matching: [.keyDown]). I am aware that global monitoring usually requires the app to be non-sandboxed. However, I am seeing some behavior I don't quite understand during development: I started with a fresh SwiftUI project and disabled the App Sandbox. I requested Accessibility permissions using AXIsProcessTrustedWithOptions, manually enabled it in System Settings, and the global monitor worked perfectly. I then re-enabled the App Sandbox in "Signing & Capabilities." To my surprise, the app still records global events from other applications, even though the Sandbox is now active. Is this expected behavior? Does macOS "remember" the trust because the Bundle ID was previously authorized while non-sandboxed, or is there a specific reason a Sandboxed app can still use addGlobalMonitor if the user has manually granted Accessibility access? My app's core feature is displaying these shortcuts for the user's own reference (productivity tracking). If the user is the one explicitly granting permission via the Accessibility privacy pane, will Apple still reject the app for using global event monitors within a Sandboxed environment? Code snippet of my monitor: // This is still firing even after re-enabling Sandbox eventMonitor = NSEvent.addGlobalMonitorForEvents(matching: [.keyDown]) { event in print("Captured: \(event.charactersIgnoringModifiers ?? "")") } I've tried cleaning the build folder and restarting the app, removing the app from accessibility permission, but the events keep coming through. I want to make sure I'm not relying on a "development glitch" before I commit to the App Store path. Here is the full code anyone can use to try this :- import SwiftUI import Cocoa import Combine struct ShortcutEvent: Identifiable { let id = UUID() let displayString: String let timestamp: Date } class KeyboardManager: ObservableObject { @Published var isCapturing = false @Published var capturedShortcuts: [ShortcutEvent] = [] private var eventMonitor: Any? // 1. Check & Request Permissions func checkAccessibilityPermissions() -> Bool { let options: NSDictionary = [kAXTrustedCheckOptionPrompt.takeUnretainedValue() as String: true] let accessEnabled = AXIsProcessTrustedWithOptions(options) return accessEnabled } // 2. Start Capture func startCapture() { guard checkAccessibilityPermissions() else { print("Permission denied") return } isCapturing = true let mask: NSEvent.EventTypeMask = [.keyDown, .keyUp] eventMonitor = NSEvent.addGlobalMonitorForEvents(matching: mask) { [weak self] event in self?.processEvent(event) } } // 3. Stop Capture func stopCapture() { if let monitor = eventMonitor { NSEvent.removeMonitor(monitor) eventMonitor = nil } isCapturing = false } private func processEvent(_ event: NSEvent) { // Only log keyDown to avoid double-counting the UI display guard event.type == .keyDown else { return } var modifiers: [String] = [] var symbols: [String] = [] // Map symbols for the UI if event.modifierFlags.contains(.command) { modifiers.append("command") symbols.append("⌘") } if event.modifierFlags.contains(.shift) { modifiers.append("shift") symbols.append("⇧") } if event.modifierFlags.contains(.option) { modifiers.append("option") symbols.append("⌥") } if event.modifierFlags.contains(.control) { modifiers.append("control") symbols.append("⌃") } let key = event.charactersIgnoringModifiers?.uppercased() ?? "" // Only display if a modifier is active (to capture "shortcuts" vs regular typing) if !symbols.isEmpty && !key.isEmpty { let shortcutString = "\(symbols.joined(separator: " ")) + \(key)" DispatchQueue.main.async { // Insert at the top so the newest shortcut is visible self.capturedShortcuts.insert(ShortcutEvent(displayString: shortcutString, timestamp: Date()), at: 0) } } } } PS :- I just did another test by creating a fresh new project with the default App Sandbox enabled, and tried and there also it worked!! Can I consider this a go to for MacOs app store than?
1
0
1.9k
Jan ’26
Overriding NSDocument.prepareSavePanel(_:) hides file format popup button
I would like to provide a default filename when saving a document depending on the document data. I thought I could do so by overriding NSDocument.prepareSavePanel(_:) and setting NSSavePanel.nameFieldStringValue, but simply implementing that method seems to hide the file format popup button shown by default (see image). Calling super doesn't help. Is it possible to set a default filename and keep the file format popup button? On macOS 15, I can toggle NSSavePanel.showsContentTypes, but how about macOS 14 and older?
Topic: UI Frameworks SubTopic: AppKit Tags:
5
0
569
Jan ’26
Using Content Inset Adjustments on macOS Tahoe with Liquid Glass in nested NSScrollViews inside Sidebar
I have the following code (compile as a standalone file): #import <Cocoa/Cocoa.h> @interface AppDelegate : NSObject <NSApplicationDelegate> @property (strong) NSWindow *window; @end @implementation AppDelegate - (void)applicationDidFinishLaunching:(NSNotification *)notification { // Create main window self.window = [[NSWindow alloc] initWithContentRect:NSMakeRect(100, 100, 800, 600) styleMask:(NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable | NSWindowStyleMaskMiniaturizable) backing:NSBackingStoreBuffered defer:NO]; [self.window setTitle:@"Nested ScrollView Demo"]; [self.window makeKeyAndOrderFront:nil]; // Split view controller NSSplitViewController *splitVC = [[NSSplitViewController alloc] init]; // Sidebar NSViewController *sidebarVC = [[NSViewController alloc] init]; sidebarVC.view = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 200, 600)]; sidebarVC.view.wantsLayer = YES; NSSplitViewItem *sidebarItem = [NSSplitViewItem sidebarWithViewController:sidebarVC]; sidebarItem.minimumThickness = 150; sidebarItem.maximumThickness = 400; [splitVC addSplitViewItem:sidebarItem]; // Content view controller NSViewController *contentVC = [[NSViewController alloc] init]; // Vertical scroll view (outer) NSScrollView *verticalScrollView = [[NSScrollView alloc] initWithFrame:NSMakeRect(0, 0, 600, 600)]; verticalScrollView.automaticallyAdjustsContentInsets = YES; verticalScrollView.hasVerticalScroller = YES; verticalScrollView.hasHorizontalScroller = NO; verticalScrollView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; NSView *verticalContent = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 600, 1200)]; verticalContent.wantsLayer = YES; verticalContent.layer.backgroundColor = [[NSColor blueColor] CGColor]; [verticalScrollView setDocumentView:verticalContent]; // Add several horizontal scroll sections CGFloat sectionHeight = 150; for (int i = 0; i < 5; i++) { // Horizontal scroll view inside section NSScrollView *horizontalScroll = [[NSScrollView alloc] initWithFrame:NSMakeRect(0, verticalContent.frame.size.height - (i+1)*sectionHeight - i*20, 600, sectionHeight)]; horizontalScroll.hasHorizontalScroller = YES; horizontalScroll.hasVerticalScroller = NO; horizontalScroll.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; NSView *horizontalContent = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 1200, sectionHeight)]; horizontalContent.wantsLayer = YES; // Add labels horizontally for (int j = 0; j < 6; j++) { NSTextField *label = [NSTextField labelWithString:[NSString stringWithFormat:@"Item %d-%d", i+1, j+1]]; label.frame = NSMakeRect(20 + j*200, sectionHeight/2 - 15, 180, 30); [horizontalContent addSubview:label]; } horizontalScroll.documentView = horizontalContent; [verticalContent addSubview:horizontalScroll]; } contentVC.view = verticalScrollView; NSSplitViewItem *contentItem = [NSSplitViewItem splitViewItemWithViewController:contentVC]; contentItem.automaticallyAdjustsSafeAreaInsets = YES; contentItem.minimumThickness = 300; [splitVC addSplitViewItem:contentItem]; self.window.contentViewController = splitVC; // Sidebar label NSTextField *label = [NSTextField labelWithString:@"Sidebar"]; label.translatesAutoresizingMaskIntoConstraints = NO; [sidebarVC.view addSubview:label]; [NSLayoutConstraint activateConstraints:@[ [label.centerXAnchor constraintEqualToAnchor:sidebarVC.view.centerXAnchor], [label.centerYAnchor constraintEqualToAnchor:sidebarVC.view.centerYAnchor] ]]; } @end int main(int argc, const char * argv[]) { @autoreleasepool { NSApplication *app = [NSApplication sharedApplication]; AppDelegate *delegate = [[AppDelegate alloc] init]; [app setDelegate:delegate]; [app run]; } return 0; } Obviously, since the contents of the right part (the content of the sidebar) has its content inset, the horizontal scrolling views cannot extend to the left beneath the sidebar. I can change line 39 to say verticalScrollView.automaticallyAdjustsContentInsets = NO; which will make the inner horizontal scroll views able to extend below the sidebar, but then I'd lose out on the automatic inset management to not have other content overlap beneath the sidebar. So what can I do here? I've tried manually changing the frame of the inner scroll views to start on a negative x, but that does not allow me to scroll all the way to the leftmost content. I'm hoping I won't have to adjust for safe areas manually for the outer scroll view. I'd also appreciate tips on how to fix the fact that veritical scrolling doesn't work when your mouse is in a horizontal scroll view. Thanks! P.S. same thing also exists on UIKit.
0
0
374
Dec ’25
AppKit Logging Internal inconsistency Errors on NSMenu on macOS 26.1
Appkit starting logging these warnings in macOS 26.1 about my app's MainMenu. **Internal inconsistency in menus - menu <NSMenu: 0xb91b2ff80> Title: AppName Supermenu: 0xb91a50b40 (Main Menu), autoenable: YES Previous menu: 0x0 (None) Next menu: 0x0 (None) Items: () believes it has [<NSMenuSubclassHereThisIsTheMenuBarMenuForMyApp:] 0xb91a50b40> Title: Main Menu Supermenu: 0x0 (None), autoenable: YES Previous menu: 0x0 (None) Next menu: 0x0 (None) Items: ( ) as a supermenu, but the supermenu does not seem to have any item with that submenu ** I don't what that means. The supermenu is the menu that represents the menu used for my app's menu bar (as described by NSMenuSubclassHereThisIsTheMenuBarMenuForMyApp Everything seems to work fine but log looks scary. Please don't throw!
Topic: UI Frameworks SubTopic: AppKit Tags:
5
0
887
Dec ’25
NSWindowController subclass in Swift
In trying to convert some Objective-C to Swift, I have a subclass of NSWindowController and want to write a convenience initializer. The documentation says You can also implement an NSWindowController subclass to avoid requiring client code to get the corresponding nib’s filename and pass it to init(windowNibName:) or init(windowNibName:owner:) when instantiating the window controller. The best way to do this is to override windowNibName to return the nib’s filename and instantiate the window controller by passing nil to init(window:). My attempt to do that looks like this: class EdgeTab: NSWindowController { override var windowNibName: NSNib.Name? { "EdgeTab" } required init?(coder: NSCoder) { super.init(coder: coder) } convenience init() { self.init( window: nil ) } } But I'm getting an error message saying "Incorrect argument label in call (have 'window:', expected 'coder:')". Why the heck is the compiler trying to use init(coder:) instead of init(window:)?
2
0
1.2k
Dec ’25
How to disable native Full Screen and implement custom "Zoom to Fill" with minimum window constraints in MacOs SwiftUI / Appkit
I am creating a macOs SwiftUI document based app, and I am struggling with the Window sizes and placements. Right now by default, a normal window has the minimize and full screen options which makes the whole window into full screen mode. However, I don't want to do this for my app. I want to only allow to fill the available width and height, i.e. exclude the status bar and doc when the user press the fill window mode, and also restrict to resize the window beyond a certain point ( which ideally to me is 1200 x 700 because I am developing on macbook air 13.3-inch in which it looks ideal, but resizing it below that makes the entire content inside messed up ). I want something like this below instead of the default full screen green When the user presses the button, it should position centered with perfect aspect ratio from my content ( or the one I want like 1200 x 700 ) and can be able to click again to fill the available width and height excluding the status bar and docs. Here is my entire @main code :- @main struct PhiaApp: App { @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate var body: some Scene { DocumentGroup(newDocument: PhiaProjectDocument()) { file in ContentView( document: file.$document, rootURL: file.fileURL ) .configureEditorWindow(disableCapture: true) .background(AppColors.background) .preferredColorScheme(.dark) } .windowStyle(.hiddenTitleBar) .windowToolbarStyle(.unified) .defaultLaunchBehavior(.suppressed) Settings { SettingsView() } } } struct WindowAccessor: NSViewRepresentable { var callback: (NSWindow?) -> Void func makeNSView(context: Context) -> NSView { let view = NSView() DispatchQueue.main.async { [weak view] in callback(view?.window) } return view } func updateNSView(_ nsView: NSView, context: Context) { } } extension View { func configureEditorWindow(disableCapture: Bool = true) -> some View { self.background( WindowAccessor { window in guard let window else { return } if let screen = window.screen ?? NSScreen.main { let visible = screen.visibleFrame window.setFrame(visible, display: true) window.minSize = visible.size } window.isMovable = true window.isMovableByWindowBackground = false window.sharingType = disableCapture ? .captureBlocked : .captureAllowed } ) } } This is a basic setup I did for now, this automatically fills the available width and height on launch, but user can resize and can go beyond my desired min width and height which makes the entire content inside messy. As I said, I want a native way of doing this, respect the content aspect ratio, don't allow to enter full screen mode, only be able to fill the available width and height excluding the status bar and doc, also don't allow to resize below my desired width and height.
1
0
989
Dec ’25
How does Apple achieve this effect?
Hi everyone, I'm new to building apps on Swift and recently I've been wondering how does Apple get this blur effect behind the control center on Mac OS Tahoe. I think it would be nice to use in an app that I'm making but I can't seem to find it in the docs. Is it available through AppKit? I would appreciate some help on this
0
0
868
Dec ’25
QLPreviewPanel takes forever to load content preview in macOS 26
After upgrading to macOS 26, I noticed that showing a Quicklook preview in my app is very slow. Showing small text files is fine, but some other files I've tried, such as a Numbers document, take about 30 seconds (during which the indeterminate loading indicator appears) before the preview is shown. When showing the preview of an app, such as Xcode, the panel opens immediately with a placeholder image for the Xcode icon, and the actual Xcode icon is shown only after about 25 seconds. During this time many logs appear: FPItemsFromURLsWithTimeout timed out (5.000000s) for: file:///.file/id=6571367.2/ (/) FPItemsFromURLsWithTimeout timed out (5.000000s) for: file:///.file/id=6571367.23684/ (/Users) FPItemsFromURLsWithTimeout timed out (5.000000s) for: file:///.file/id=6571367.248032/ (/Users/n{9}k) FPItemsFromURLsWithTimeout timed out (5.000000s) for: file:///.file/id=6571367.248084/ (/Users/n{9}k/Downloads) Failed to add registration dmf.policy.monitor.app with error: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.apple.dmd.policy was invalidated: failed at lookup with error 159 - Sandbox restriction." UserInfo={NSDebugDescription=The connection to service named com.apple.dmd.policy was invalidated: failed at lookup with error 159 - Sandbox restriction.} Failed to register application policy monitor with identifier 69DDBDB4-0736-42FA-BA7A-C8D7EA049E29 for types {( applicationcategories, websites, categories, applications )} with error: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.apple.dmd.policy was invalidated: failed at lookup with error 159 - Sandbox restriction." UserInfo={NSDebugDescription=The connection to service named com.apple.dmd.policy was invalidated: failed at lookup with error 159 - Sandbox restriction.} FPItemsFromURLsWithTimeout timed out (5.000000s) for: file:///.file/id=6571367.155797561/ (~/Downloads/X{3}e.app) It seems that Quicklook tries to access each parent directory of the previewed file, and each one fails after 5 seconds. Why is Quicklook all of a sudden so slow? It used to be almost instant in macOS 15. I created FB20268201. import Cocoa import Quartz @main class AppDelegate: NSObject, NSApplicationDelegate, QLPreviewPanelDataSource, QLPreviewPanelDelegate { var url: URL? func applicationDidFinishLaunching(_ notification: Notification) { let openPanel = NSOpenPanel() openPanel.runModal() url = openPanel.urls[0] QLPreviewPanel.shared()!.makeKeyAndOrderFront(nil) } override func acceptsPreviewPanelControl(_ panel: QLPreviewPanel!) -> Bool { return true } override func beginPreviewPanelControl(_ panel: QLPreviewPanel!) { panel.dataSource = self panel.delegate = self } override func endPreviewPanelControl(_ panel: QLPreviewPanel!) { panel.dataSource = nil panel.delegate = nil } func numberOfPreviewItems(in panel: QLPreviewPanel!) -> Int { return 1 } func previewPanel(_ panel: QLPreviewPanel!, previewItemAt index: Int) -> QLPreviewItem! { return url as? QLPreviewItem } }
5
1
1.3k
Dec ’25
NSWorkspace openURL fails on file in iCloud Drive
When I pass a file path url of a file in iCloud Drive to -[NSWorkspace openURLs:withApplicationAtURL:configuration:completionHandler:], it fails. There is no exception, and the completion handler isn't called. This is in a sandboxed app on macOS 26.1. NSWorkspaceOpenConfiguration* config = NSWorkspaceOpenConfiguration.configuration; config.activates = YES; config.promptsUserIfNeeded = YES; NSLog(@"performDrag 2 with %@", filePathObs); [NSWorkspace.sharedWorkspace openURLs: filePathObs withApplicationAtURL: appURL configuration: config completionHandler: ^(NSRunningApplication * _Nullable app, NSError * _Nullable error) { NSLog(@"performDrag 3"); if (error != nil) { NSLog(@"%@\n%@", error, filePathObs); } NSLog(@"complete performDrag"); }]; NSLog(@"performDrag 4"); In the debug log, the performDrag 2 and performDrag 4 messages appear. I also looked in the Console log, but the only messages that mention my app don't mean anything to me. AFIsDeviceGreymatterEligible Missing entitlements for os_eligibility lookup 6c Reentrant message: kDragIPCCompleted, current message: kDragIPCLeaveApplication
8
0
1.8k
Dec ’25
NSBox Basically Not Visible At All on macOS Tahoe in Light Mode?
I noticed that I cannot even tell that an NSBox is being used on macOS Tahoe when the system is in light mode. The 'box' background can't be seen so it makes it appear that the subviews in the box aren't positioned correctly (because they are inset from the subview outside the box). There is no visual indicator that that subviews inside this box are grouped together because well, you can't see the box at all. In Interface Builder the box looks fine at Design Time in "Light Mode". In Dark Mode the box looks fine at design time and at run time. Just figured I'd throw that out there.
Topic: UI Frameworks SubTopic: AppKit Tags:
2
0
494
Dec ’25
NSSheetMoveHelper Sends Parent Windows Flying If Sheet Window Frame is Resized on macOS Tahoe
So I noticed this: A sheet window is presented. The sheet window has some UI that makes it expandable say a little arrow expandable button. Click the little expandable button. Now the sheet window controller calls - (void)setFrame:display:animate: on its window to resize. The parent window flies across the screen to the lower left corner. I'm on Tahoe 26.1. Seems to be related to NSSheetMoveHelper. Not sure how long this bug has been around. Workaround is to call -setFrame:display:animate: and pass NO to the animate flag. Then the sheet window resizes (but not animated which doesn't look as good as the old behavior but better than suddenly disappearing). I think Apple may already knows about this bug b/c in an Apple app on Tahoe I see a sheet resizing being done with no animation...
Topic: UI Frameworks SubTopic: AppKit Tags:
1
0
385
Dec ’25
Resources for Retro style Games wanting 90 degree Window corners
I've been thinking of bringing some older games back to the modern Mac. Rewriting old titles in Swift but using the original data files that assume use of non-rounded corners Windows. Many of these games require all the Window space of a 90 degree cornered Window. Can anyone point me at some useful workarounds or Is Apple simply deaf to the needs of this type of product?
2
1
1.5k
Dec ’25
How can I show a movable webcam preview above all windows in macOS without activating the app
I'm building a macOS app using SwiftUI, and I want to create a draggable floating webcam preview window Right now, I have something like this: import SwiftUI import AVFoundation struct WebcamPreviewView: View { let captureSession: AVCaptureSession? var body: some View { ZStack { if let session = captureSession { CameraPreviewLayer(session: session) .clipShape(RoundedRectangle(cornerRadius: 50)) .overlay( RoundedRectangle(cornerRadius: 50) .strokeBorder(Color.white.opacity(0.2), lineWidth: 2) ) } else { VStack(spacing: 8) { Image(systemName: "video.slash.fill") .font(.system(size: 40)) .foregroundColor(.white.opacity(0.6)) Text("No Camera") .font(.caption) .foregroundColor(.white.opacity(0.6)) } } } .shadow(color: .black.opacity(0.3), radius: 10, x: 0, y: 5) } } struct CameraPreviewLayer: NSViewRepresentable { let session: AVCaptureSession func makeNSView(context: Context) -> NSView { let view = NSView() view.wantsLayer = true let previewLayer = AVCaptureVideoPreviewLayer(session: session) previewLayer.videoGravity = .resizeAspectFill previewLayer.frame = view.bounds view.layer = previewLayer return view } func updateNSView(_ nsView: NSView, context: Context) { if let previewLayer = nsView.layer as? AVCaptureVideoPreviewLayer { previewLayer.frame = nsView.bounds } } } This is my SwiftUI side code to show the webcam, and I am trying to create it as a floating window which appears on top of all other apps windows etc. however, even when the webcam is clicked, it should not steal the focus from other apps, the other apps should be able to function properly as they already are. import Cocoa import SwiftUI class WebcamPreviewWindow: NSPanel { private static let defaultSize = CGSize(width: 200, height: 200) private var initialClickLocation: NSPoint = .zero init() { let screenFrame = NSScreen.main?.visibleFrame ?? .zero let origin = CGPoint( x: screenFrame.maxX - Self.defaultSize.width - 20, y: screenFrame.minY + 20 ) super.init( contentRect: CGRect(origin: origin, size: Self.defaultSize), styleMask: [.borderless], backing: .buffered, defer: false ) isOpaque = false backgroundColor = .clear hasShadow = false level = .screenSaver collectionBehavior = [ .canJoinAllSpaces, .fullScreenAuxiliary, .stationary, .ignoresCycle ] ignoresMouseEvents = false acceptsMouseMovedEvents = true hidesOnDeactivate = false becomesKeyOnlyIfNeeded = false } // MARK: - Focus Prevention override var canBecomeKey: Bool { false } override var canBecomeMain: Bool { false } override var acceptsFirstResponder: Bool { false } override func makeKey() { } override func mouseDown(with event: NSEvent) { initialClickLocation = event.locationInWindow } override func mouseDragged(with event: NSEvent) { let current = event.locationInWindow let dx = current.x - initialClickLocation.x let dy = current.y - initialClickLocation.y let newOrigin = CGPoint( x: frame.origin.x + dx, y: frame.origin.y + dy ) setFrameOrigin(newOrigin) } func show<Content: View>(with view: Content) { let host = NSHostingView(rootView: view) host.autoresizingMask = [.width, .height] host.frame = contentLayoutRect contentView = host orderFrontRegardless() } func hide() { orderOut(nil) contentView = nil } } This is my Appkit Side code make a floating window, however, when the webcam preview is clicked, it makes it as the focus app and I have to click anywhere else to loose the focus to be able to use the rest of the windows.
0
0
736
Nov ’25
[macOS Sequoia] Using RegisterEventHotkey with option and shift modifiers doesn't working anymore
Hello. In my app, I use RegisterEventHotkey to implement global keyboard shortcuts to trigger actions. Up until macOS Sequoia, I was able to use a keyboard shortcut with option and shift as the modifiers, like option shift 2 (⌥ ⇧ 2). Now, on macOS Sequoia, using RegisterEventHotkey to register a hotkey with those exact modifiers (option and shift), regardless of the key, fails with the error -9868 (eventInternalErr). Is this a documented and wanted change, or is this a bug? Other modifier keys (just command, command option, command shift, command control, control shift, etc), all work. Any insight into this would be appreciated. (Feedback filed: FB15163561) Thank you, Matthias
22
10
16k
Nov ’25
macOS Tahoe: NSView -cacheDisplayInRect:toBitmapImageRep: Doesn't Work Unless View is Added to Window
Previously I was able to "snapshot" view that were not part of any window hierarchy using the following: NSImage *buttonImage = [NSImage imageWithSystemSymbolName:@"49.circle.fill" accessibilityDescription:nil]; NSButton *aButton = [NSButton buttonWithImage:buttonImage target:nil action:nil]; [aButton sizeToFit]; NSBitmapImageRep *rep = [aButton bitmapImageRepForCachingDisplayInRect:aButton.bounds]; if (rep == nil) { NSLog(@"Failed to get bitmap image rep."); return; } [aButton cacheDisplayInRect:aButton.bounds toBitmapImageRep:rep]; NSData *tiffData = rep.TIFFRepresentation; NSImage *snapShotOfImage = [[NSImage alloc]initWithData:tiffData]; Now on macOS Tahoe I get a non nil image, but the image is blank. However if I add aButton NSWindow's view hiearchy just before the call to -cacheDisplayInRect:toBitmapImageRep: I do get a proper image. Is this behavior intended or is this considered a bug? Is it documented anywhere that a view must be in a NSWindow for -cacheDisplayInRect:toBitmapImageRep: to work? Thanks
Topic: UI Frameworks SubTopic: AppKit Tags:
2
0
405
Nov ’25
Fetching Tinted Folder Icons in macOS Tahoe using Swift
In macOS Tahoe, users can tint folders or add symbols. But when trying to access that customized icon in Swift, the system always returns the default folder icon. NSWorkspace.shared.icon(forFile: url.path) try url.resourceValues(forKeys: [.effectiveIconKey]).effectiveIcon try url.resourceValues(forKeys: [.customIconKey]).customIconKey All of these give back the standard folder icon without any of the user-applied customization. So the question is: Is there any API or workaround in Swift to retrieve the actual customized folder icon (including tint and symbol) as displayed in Finder on macOS Tahoe?
1
0
450
Nov ’25
Detecting marked range in UI/NSTextViews at the time of shouldChangeTextIn
We have submitted a feedback for this issue: FB21230723 We're building a note-taking app for iOS and macOS that uses both UITextView and NSTextView. When performing text input that involves a marked range (such as Japanese input) in a UITextView or NSTextView with a UITextViewDelegate or NSTextViewDelegate set, the text view's marked range (markedTextRange / markedRange()) has not yet been updated at the moment when shouldChangeTextIn is invoked. UITextViewDelegate.textView(_:shouldChangeTextIn:replacementText:) NSTextViewDelegate.textView(_:shouldChangeTextIn:replacementString:) The current behavior is this when entering text in Japanese: (same for NSTextView) func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { print(textView.markedTextRange != nil) // prints out false DispatchQueue.main.async { print(textView.markedTextRange != nil) // prints out true } } However, we need the value of markedTextRange right away in order to determine whether to return true or false from this method. Is there any workaround for this issue?
Replies
6
Boosts
0
Views
1.2k
Activity
Jan ’26
Changing the menu bar display name
Hello, I'm currently working on an app that will have a different name (and UI) depending on an environment variable that is set by that app's custom installer that I also wrote. I'm trying to change the app name that is displayed in the menu bar (top left) programmatically. I've done some research and found that it's probably not possible to do so because it's fetched from the app's Info.plist The answer is probably already there but I'll ask the question: Is it possible to change the app's name in the menu bar without tampering with the Info.plist (as it will break the signature at runtime, and it can't be done at compile time) The use case here is that I'm shipping a single app with multiple installers, because the app will be the same for all sets of users but it will have minor UI changes (which in my opinion, don't need an entire separate release), the installers will set a flag that the app will, based on, change its UI to the corresponding set of users. For the most part it's been successful but only small issue remain like this one. The reason it's done like that is when updating I'll ship 1 release for all users to update rather than having to ship multiple releases with no difference between them
Replies
1
Boosts
0
Views
1.2k
Activity
Jan ’26
NSPathControl -setURL: crash on macOS Tahoe
I received the following crash: Thread 0 Crashed: libsystem_kernel.dylib __pthread_kill + 8 libsystem_pthread.dylib pthread_kill + 296 (pthread.c:1721) libsystem_c.dylib abort + 124 (abort.c:122) libc++abi.dylib __abort_message + 132 (abort_message.cpp:66) libc++abi.dylib demangling_terminate_handler() + 304 (cxa_default_handlers.cpp:76) libobjc.A.dylib _objc_terminate() + 156 (objc-exception.mm:496) libc++abi.dylib std::__terminate(void (*)()) + 16 (cxa_handlers.cpp:59) libc++abi.dylib __cxxabiv1::failed_throw(__cxxabiv1::__cxa_exception*) + 88 (cxa_exception.cpp:152) libc++abi.dylib __cxa_throw + 92 (cxa_exception.cpp:299) libobjc.A.dylib objc_exception_throw + 448 (objc-exception.mm:385) Foundation -[NSConcreteMutableAttributedString initWithString:] + 268 (NSAttributedString.m:1049) CloudDocs -[BRCloudPathComponentDisplayMetadata initWithDisplayName:suffix:url:icon:] + 180 (BRCloudPathComponentDisplayMetadata.m:75) CloudDocs -[NSURL(BRCloudPathComponent) br_pathComponentDisplayMetadataWithOptions:]_block_invoke + 516 (BRCloudPathComponentDisplayMetadata.m:292) CloudDocs -[NSArray(BRAdditions) br_transform:keepNull:] + 228 (NSArray+BRAdditions.m:20) CloudDocs -[NSURL(BRCloudPathComponent) br_pathComponentDisplayMetadataWithOptions:] + 76 (BRCloudPathComponentDisplayMetadata.m:276) AppKit -[NSPathCell _autoUpdateCellContents] + 2080 (NSPathCell.m:442) AppKit -[NSPathCell setURL:] + 76 (NSPathCell.m:599) AppKit -[NSPathControl setURL:] + 64 (NSPathControl.m:366) I tried reproducing on my end by passing various URLs in iCloud Drive to an NSPathControl, file reference urls, attempting to evict a URL from iCloud Drive then settings the URL property without luck. Setting the URL to nil does not crash (the property is nullable). I have no idea how to trigger that code path. Anyone else run into this and have a workaround?
Replies
2
Boosts
0
Views
1.1k
Activity
Jan ’26
Why does NSEvent.addGlobalMonitorForEvents still work in a Sandboxed macOS app
I am building a macOS utility using SwiftUI and Swift that records and displays keyboard shortcuts (like Cmd+C, Cmd+V) in the UI. To achieve this, I am using NSEvent.addGlobalMonitorForEvents(matching: [.keyDown]). I am aware that global monitoring usually requires the app to be non-sandboxed. However, I am seeing some behavior I don't quite understand during development: I started with a fresh SwiftUI project and disabled the App Sandbox. I requested Accessibility permissions using AXIsProcessTrustedWithOptions, manually enabled it in System Settings, and the global monitor worked perfectly. I then re-enabled the App Sandbox in "Signing & Capabilities." To my surprise, the app still records global events from other applications, even though the Sandbox is now active. Is this expected behavior? Does macOS "remember" the trust because the Bundle ID was previously authorized while non-sandboxed, or is there a specific reason a Sandboxed app can still use addGlobalMonitor if the user has manually granted Accessibility access? My app's core feature is displaying these shortcuts for the user's own reference (productivity tracking). If the user is the one explicitly granting permission via the Accessibility privacy pane, will Apple still reject the app for using global event monitors within a Sandboxed environment? Code snippet of my monitor: // This is still firing even after re-enabling Sandbox eventMonitor = NSEvent.addGlobalMonitorForEvents(matching: [.keyDown]) { event in print("Captured: \(event.charactersIgnoringModifiers ?? "")") } I've tried cleaning the build folder and restarting the app, removing the app from accessibility permission, but the events keep coming through. I want to make sure I'm not relying on a "development glitch" before I commit to the App Store path. Here is the full code anyone can use to try this :- import SwiftUI import Cocoa import Combine struct ShortcutEvent: Identifiable { let id = UUID() let displayString: String let timestamp: Date } class KeyboardManager: ObservableObject { @Published var isCapturing = false @Published var capturedShortcuts: [ShortcutEvent] = [] private var eventMonitor: Any? // 1. Check & Request Permissions func checkAccessibilityPermissions() -> Bool { let options: NSDictionary = [kAXTrustedCheckOptionPrompt.takeUnretainedValue() as String: true] let accessEnabled = AXIsProcessTrustedWithOptions(options) return accessEnabled } // 2. Start Capture func startCapture() { guard checkAccessibilityPermissions() else { print("Permission denied") return } isCapturing = true let mask: NSEvent.EventTypeMask = [.keyDown, .keyUp] eventMonitor = NSEvent.addGlobalMonitorForEvents(matching: mask) { [weak self] event in self?.processEvent(event) } } // 3. Stop Capture func stopCapture() { if let monitor = eventMonitor { NSEvent.removeMonitor(monitor) eventMonitor = nil } isCapturing = false } private func processEvent(_ event: NSEvent) { // Only log keyDown to avoid double-counting the UI display guard event.type == .keyDown else { return } var modifiers: [String] = [] var symbols: [String] = [] // Map symbols for the UI if event.modifierFlags.contains(.command) { modifiers.append("command") symbols.append("⌘") } if event.modifierFlags.contains(.shift) { modifiers.append("shift") symbols.append("⇧") } if event.modifierFlags.contains(.option) { modifiers.append("option") symbols.append("⌥") } if event.modifierFlags.contains(.control) { modifiers.append("control") symbols.append("⌃") } let key = event.charactersIgnoringModifiers?.uppercased() ?? "" // Only display if a modifier is active (to capture "shortcuts" vs regular typing) if !symbols.isEmpty && !key.isEmpty { let shortcutString = "\(symbols.joined(separator: " ")) + \(key)" DispatchQueue.main.async { // Insert at the top so the newest shortcut is visible self.capturedShortcuts.insert(ShortcutEvent(displayString: shortcutString, timestamp: Date()), at: 0) } } } } PS :- I just did another test by creating a fresh new project with the default App Sandbox enabled, and tried and there also it worked!! Can I consider this a go to for MacOs app store than?
Replies
1
Boosts
0
Views
1.9k
Activity
Jan ’26
Overriding NSDocument.prepareSavePanel(_:) hides file format popup button
I would like to provide a default filename when saving a document depending on the document data. I thought I could do so by overriding NSDocument.prepareSavePanel(_:) and setting NSSavePanel.nameFieldStringValue, but simply implementing that method seems to hide the file format popup button shown by default (see image). Calling super doesn't help. Is it possible to set a default filename and keep the file format popup button? On macOS 15, I can toggle NSSavePanel.showsContentTypes, but how about macOS 14 and older?
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
5
Boosts
0
Views
569
Activity
Jan ’26
Using Content Inset Adjustments on macOS Tahoe with Liquid Glass in nested NSScrollViews inside Sidebar
I have the following code (compile as a standalone file): #import <Cocoa/Cocoa.h> @interface AppDelegate : NSObject <NSApplicationDelegate> @property (strong) NSWindow *window; @end @implementation AppDelegate - (void)applicationDidFinishLaunching:(NSNotification *)notification { // Create main window self.window = [[NSWindow alloc] initWithContentRect:NSMakeRect(100, 100, 800, 600) styleMask:(NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable | NSWindowStyleMaskMiniaturizable) backing:NSBackingStoreBuffered defer:NO]; [self.window setTitle:@"Nested ScrollView Demo"]; [self.window makeKeyAndOrderFront:nil]; // Split view controller NSSplitViewController *splitVC = [[NSSplitViewController alloc] init]; // Sidebar NSViewController *sidebarVC = [[NSViewController alloc] init]; sidebarVC.view = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 200, 600)]; sidebarVC.view.wantsLayer = YES; NSSplitViewItem *sidebarItem = [NSSplitViewItem sidebarWithViewController:sidebarVC]; sidebarItem.minimumThickness = 150; sidebarItem.maximumThickness = 400; [splitVC addSplitViewItem:sidebarItem]; // Content view controller NSViewController *contentVC = [[NSViewController alloc] init]; // Vertical scroll view (outer) NSScrollView *verticalScrollView = [[NSScrollView alloc] initWithFrame:NSMakeRect(0, 0, 600, 600)]; verticalScrollView.automaticallyAdjustsContentInsets = YES; verticalScrollView.hasVerticalScroller = YES; verticalScrollView.hasHorizontalScroller = NO; verticalScrollView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; NSView *verticalContent = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 600, 1200)]; verticalContent.wantsLayer = YES; verticalContent.layer.backgroundColor = [[NSColor blueColor] CGColor]; [verticalScrollView setDocumentView:verticalContent]; // Add several horizontal scroll sections CGFloat sectionHeight = 150; for (int i = 0; i < 5; i++) { // Horizontal scroll view inside section NSScrollView *horizontalScroll = [[NSScrollView alloc] initWithFrame:NSMakeRect(0, verticalContent.frame.size.height - (i+1)*sectionHeight - i*20, 600, sectionHeight)]; horizontalScroll.hasHorizontalScroller = YES; horizontalScroll.hasVerticalScroller = NO; horizontalScroll.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; NSView *horizontalContent = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 1200, sectionHeight)]; horizontalContent.wantsLayer = YES; // Add labels horizontally for (int j = 0; j < 6; j++) { NSTextField *label = [NSTextField labelWithString:[NSString stringWithFormat:@"Item %d-%d", i+1, j+1]]; label.frame = NSMakeRect(20 + j*200, sectionHeight/2 - 15, 180, 30); [horizontalContent addSubview:label]; } horizontalScroll.documentView = horizontalContent; [verticalContent addSubview:horizontalScroll]; } contentVC.view = verticalScrollView; NSSplitViewItem *contentItem = [NSSplitViewItem splitViewItemWithViewController:contentVC]; contentItem.automaticallyAdjustsSafeAreaInsets = YES; contentItem.minimumThickness = 300; [splitVC addSplitViewItem:contentItem]; self.window.contentViewController = splitVC; // Sidebar label NSTextField *label = [NSTextField labelWithString:@"Sidebar"]; label.translatesAutoresizingMaskIntoConstraints = NO; [sidebarVC.view addSubview:label]; [NSLayoutConstraint activateConstraints:@[ [label.centerXAnchor constraintEqualToAnchor:sidebarVC.view.centerXAnchor], [label.centerYAnchor constraintEqualToAnchor:sidebarVC.view.centerYAnchor] ]]; } @end int main(int argc, const char * argv[]) { @autoreleasepool { NSApplication *app = [NSApplication sharedApplication]; AppDelegate *delegate = [[AppDelegate alloc] init]; [app setDelegate:delegate]; [app run]; } return 0; } Obviously, since the contents of the right part (the content of the sidebar) has its content inset, the horizontal scrolling views cannot extend to the left beneath the sidebar. I can change line 39 to say verticalScrollView.automaticallyAdjustsContentInsets = NO; which will make the inner horizontal scroll views able to extend below the sidebar, but then I'd lose out on the automatic inset management to not have other content overlap beneath the sidebar. So what can I do here? I've tried manually changing the frame of the inner scroll views to start on a negative x, but that does not allow me to scroll all the way to the leftmost content. I'm hoping I won't have to adjust for safe areas manually for the outer scroll view. I'd also appreciate tips on how to fix the fact that veritical scrolling doesn't work when your mouse is in a horizontal scroll view. Thanks! P.S. same thing also exists on UIKit.
Replies
0
Boosts
0
Views
374
Activity
Dec ’25
AppKit Logging Internal inconsistency Errors on NSMenu on macOS 26.1
Appkit starting logging these warnings in macOS 26.1 about my app's MainMenu. **Internal inconsistency in menus - menu <NSMenu: 0xb91b2ff80> Title: AppName Supermenu: 0xb91a50b40 (Main Menu), autoenable: YES Previous menu: 0x0 (None) Next menu: 0x0 (None) Items: () believes it has [<NSMenuSubclassHereThisIsTheMenuBarMenuForMyApp:] 0xb91a50b40> Title: Main Menu Supermenu: 0x0 (None), autoenable: YES Previous menu: 0x0 (None) Next menu: 0x0 (None) Items: ( ) as a supermenu, but the supermenu does not seem to have any item with that submenu ** I don't what that means. The supermenu is the menu that represents the menu used for my app's menu bar (as described by NSMenuSubclassHereThisIsTheMenuBarMenuForMyApp Everything seems to work fine but log looks scary. Please don't throw!
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
5
Boosts
0
Views
887
Activity
Dec ’25
NSWindowController subclass in Swift
In trying to convert some Objective-C to Swift, I have a subclass of NSWindowController and want to write a convenience initializer. The documentation says You can also implement an NSWindowController subclass to avoid requiring client code to get the corresponding nib’s filename and pass it to init(windowNibName:) or init(windowNibName:owner:) when instantiating the window controller. The best way to do this is to override windowNibName to return the nib’s filename and instantiate the window controller by passing nil to init(window:). My attempt to do that looks like this: class EdgeTab: NSWindowController { override var windowNibName: NSNib.Name? { "EdgeTab" } required init?(coder: NSCoder) { super.init(coder: coder) } convenience init() { self.init( window: nil ) } } But I'm getting an error message saying "Incorrect argument label in call (have 'window:', expected 'coder:')". Why the heck is the compiler trying to use init(coder:) instead of init(window:)?
Replies
2
Boosts
0
Views
1.2k
Activity
Dec ’25
How to disable native Full Screen and implement custom "Zoom to Fill" with minimum window constraints in MacOs SwiftUI / Appkit
I am creating a macOs SwiftUI document based app, and I am struggling with the Window sizes and placements. Right now by default, a normal window has the minimize and full screen options which makes the whole window into full screen mode. However, I don't want to do this for my app. I want to only allow to fill the available width and height, i.e. exclude the status bar and doc when the user press the fill window mode, and also restrict to resize the window beyond a certain point ( which ideally to me is 1200 x 700 because I am developing on macbook air 13.3-inch in which it looks ideal, but resizing it below that makes the entire content inside messed up ). I want something like this below instead of the default full screen green When the user presses the button, it should position centered with perfect aspect ratio from my content ( or the one I want like 1200 x 700 ) and can be able to click again to fill the available width and height excluding the status bar and docs. Here is my entire @main code :- @main struct PhiaApp: App { @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate var body: some Scene { DocumentGroup(newDocument: PhiaProjectDocument()) { file in ContentView( document: file.$document, rootURL: file.fileURL ) .configureEditorWindow(disableCapture: true) .background(AppColors.background) .preferredColorScheme(.dark) } .windowStyle(.hiddenTitleBar) .windowToolbarStyle(.unified) .defaultLaunchBehavior(.suppressed) Settings { SettingsView() } } } struct WindowAccessor: NSViewRepresentable { var callback: (NSWindow?) -> Void func makeNSView(context: Context) -> NSView { let view = NSView() DispatchQueue.main.async { [weak view] in callback(view?.window) } return view } func updateNSView(_ nsView: NSView, context: Context) { } } extension View { func configureEditorWindow(disableCapture: Bool = true) -> some View { self.background( WindowAccessor { window in guard let window else { return } if let screen = window.screen ?? NSScreen.main { let visible = screen.visibleFrame window.setFrame(visible, display: true) window.minSize = visible.size } window.isMovable = true window.isMovableByWindowBackground = false window.sharingType = disableCapture ? .captureBlocked : .captureAllowed } ) } } This is a basic setup I did for now, this automatically fills the available width and height on launch, but user can resize and can go beyond my desired min width and height which makes the entire content inside messy. As I said, I want a native way of doing this, respect the content aspect ratio, don't allow to enter full screen mode, only be able to fill the available width and height excluding the status bar and doc, also don't allow to resize below my desired width and height.
Replies
1
Boosts
0
Views
989
Activity
Dec ’25
How does Apple achieve this effect?
Hi everyone, I'm new to building apps on Swift and recently I've been wondering how does Apple get this blur effect behind the control center on Mac OS Tahoe. I think it would be nice to use in an app that I'm making but I can't seem to find it in the docs. Is it available through AppKit? I would appreciate some help on this
Replies
0
Boosts
0
Views
868
Activity
Dec ’25
QLPreviewPanel takes forever to load content preview in macOS 26
After upgrading to macOS 26, I noticed that showing a Quicklook preview in my app is very slow. Showing small text files is fine, but some other files I've tried, such as a Numbers document, take about 30 seconds (during which the indeterminate loading indicator appears) before the preview is shown. When showing the preview of an app, such as Xcode, the panel opens immediately with a placeholder image for the Xcode icon, and the actual Xcode icon is shown only after about 25 seconds. During this time many logs appear: FPItemsFromURLsWithTimeout timed out (5.000000s) for: file:///.file/id=6571367.2/ (/) FPItemsFromURLsWithTimeout timed out (5.000000s) for: file:///.file/id=6571367.23684/ (/Users) FPItemsFromURLsWithTimeout timed out (5.000000s) for: file:///.file/id=6571367.248032/ (/Users/n{9}k) FPItemsFromURLsWithTimeout timed out (5.000000s) for: file:///.file/id=6571367.248084/ (/Users/n{9}k/Downloads) Failed to add registration dmf.policy.monitor.app with error: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.apple.dmd.policy was invalidated: failed at lookup with error 159 - Sandbox restriction." UserInfo={NSDebugDescription=The connection to service named com.apple.dmd.policy was invalidated: failed at lookup with error 159 - Sandbox restriction.} Failed to register application policy monitor with identifier 69DDBDB4-0736-42FA-BA7A-C8D7EA049E29 for types {( applicationcategories, websites, categories, applications )} with error: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.apple.dmd.policy was invalidated: failed at lookup with error 159 - Sandbox restriction." UserInfo={NSDebugDescription=The connection to service named com.apple.dmd.policy was invalidated: failed at lookup with error 159 - Sandbox restriction.} FPItemsFromURLsWithTimeout timed out (5.000000s) for: file:///.file/id=6571367.155797561/ (~/Downloads/X{3}e.app) It seems that Quicklook tries to access each parent directory of the previewed file, and each one fails after 5 seconds. Why is Quicklook all of a sudden so slow? It used to be almost instant in macOS 15. I created FB20268201. import Cocoa import Quartz @main class AppDelegate: NSObject, NSApplicationDelegate, QLPreviewPanelDataSource, QLPreviewPanelDelegate { var url: URL? func applicationDidFinishLaunching(_ notification: Notification) { let openPanel = NSOpenPanel() openPanel.runModal() url = openPanel.urls[0] QLPreviewPanel.shared()!.makeKeyAndOrderFront(nil) } override func acceptsPreviewPanelControl(_ panel: QLPreviewPanel!) -> Bool { return true } override func beginPreviewPanelControl(_ panel: QLPreviewPanel!) { panel.dataSource = self panel.delegate = self } override func endPreviewPanelControl(_ panel: QLPreviewPanel!) { panel.dataSource = nil panel.delegate = nil } func numberOfPreviewItems(in panel: QLPreviewPanel!) -> Int { return 1 } func previewPanel(_ panel: QLPreviewPanel!, previewItemAt index: Int) -> QLPreviewItem! { return url as? QLPreviewItem } }
Replies
5
Boosts
1
Views
1.3k
Activity
Dec ’25
NSWorkspace openURL fails on file in iCloud Drive
When I pass a file path url of a file in iCloud Drive to -[NSWorkspace openURLs:withApplicationAtURL:configuration:completionHandler:], it fails. There is no exception, and the completion handler isn't called. This is in a sandboxed app on macOS 26.1. NSWorkspaceOpenConfiguration* config = NSWorkspaceOpenConfiguration.configuration; config.activates = YES; config.promptsUserIfNeeded = YES; NSLog(@"performDrag 2 with %@", filePathObs); [NSWorkspace.sharedWorkspace openURLs: filePathObs withApplicationAtURL: appURL configuration: config completionHandler: ^(NSRunningApplication * _Nullable app, NSError * _Nullable error) { NSLog(@"performDrag 3"); if (error != nil) { NSLog(@"%@\n%@", error, filePathObs); } NSLog(@"complete performDrag"); }]; NSLog(@"performDrag 4"); In the debug log, the performDrag 2 and performDrag 4 messages appear. I also looked in the Console log, but the only messages that mention my app don't mean anything to me. AFIsDeviceGreymatterEligible Missing entitlements for os_eligibility lookup 6c Reentrant message: kDragIPCCompleted, current message: kDragIPCLeaveApplication
Replies
8
Boosts
0
Views
1.8k
Activity
Dec ’25
NSBox Basically Not Visible At All on macOS Tahoe in Light Mode?
I noticed that I cannot even tell that an NSBox is being used on macOS Tahoe when the system is in light mode. The 'box' background can't be seen so it makes it appear that the subviews in the box aren't positioned correctly (because they are inset from the subview outside the box). There is no visual indicator that that subviews inside this box are grouped together because well, you can't see the box at all. In Interface Builder the box looks fine at Design Time in "Light Mode". In Dark Mode the box looks fine at design time and at run time. Just figured I'd throw that out there.
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
2
Boosts
0
Views
494
Activity
Dec ’25
NSSheetMoveHelper Sends Parent Windows Flying If Sheet Window Frame is Resized on macOS Tahoe
So I noticed this: A sheet window is presented. The sheet window has some UI that makes it expandable say a little arrow expandable button. Click the little expandable button. Now the sheet window controller calls - (void)setFrame:display:animate: on its window to resize. The parent window flies across the screen to the lower left corner. I'm on Tahoe 26.1. Seems to be related to NSSheetMoveHelper. Not sure how long this bug has been around. Workaround is to call -setFrame:display:animate: and pass NO to the animate flag. Then the sheet window resizes (but not animated which doesn't look as good as the old behavior but better than suddenly disappearing). I think Apple may already knows about this bug b/c in an Apple app on Tahoe I see a sheet resizing being done with no animation...
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
1
Boosts
0
Views
385
Activity
Dec ’25
Resources for Retro style Games wanting 90 degree Window corners
I've been thinking of bringing some older games back to the modern Mac. Rewriting old titles in Swift but using the original data files that assume use of non-rounded corners Windows. Many of these games require all the Window space of a 90 degree cornered Window. Can anyone point me at some useful workarounds or Is Apple simply deaf to the needs of this type of product?
Replies
2
Boosts
1
Views
1.5k
Activity
Dec ’25
How can I show a movable webcam preview above all windows in macOS without activating the app
I'm building a macOS app using SwiftUI, and I want to create a draggable floating webcam preview window Right now, I have something like this: import SwiftUI import AVFoundation struct WebcamPreviewView: View { let captureSession: AVCaptureSession? var body: some View { ZStack { if let session = captureSession { CameraPreviewLayer(session: session) .clipShape(RoundedRectangle(cornerRadius: 50)) .overlay( RoundedRectangle(cornerRadius: 50) .strokeBorder(Color.white.opacity(0.2), lineWidth: 2) ) } else { VStack(spacing: 8) { Image(systemName: "video.slash.fill") .font(.system(size: 40)) .foregroundColor(.white.opacity(0.6)) Text("No Camera") .font(.caption) .foregroundColor(.white.opacity(0.6)) } } } .shadow(color: .black.opacity(0.3), radius: 10, x: 0, y: 5) } } struct CameraPreviewLayer: NSViewRepresentable { let session: AVCaptureSession func makeNSView(context: Context) -> NSView { let view = NSView() view.wantsLayer = true let previewLayer = AVCaptureVideoPreviewLayer(session: session) previewLayer.videoGravity = .resizeAspectFill previewLayer.frame = view.bounds view.layer = previewLayer return view } func updateNSView(_ nsView: NSView, context: Context) { if let previewLayer = nsView.layer as? AVCaptureVideoPreviewLayer { previewLayer.frame = nsView.bounds } } } This is my SwiftUI side code to show the webcam, and I am trying to create it as a floating window which appears on top of all other apps windows etc. however, even when the webcam is clicked, it should not steal the focus from other apps, the other apps should be able to function properly as they already are. import Cocoa import SwiftUI class WebcamPreviewWindow: NSPanel { private static let defaultSize = CGSize(width: 200, height: 200) private var initialClickLocation: NSPoint = .zero init() { let screenFrame = NSScreen.main?.visibleFrame ?? .zero let origin = CGPoint( x: screenFrame.maxX - Self.defaultSize.width - 20, y: screenFrame.minY + 20 ) super.init( contentRect: CGRect(origin: origin, size: Self.defaultSize), styleMask: [.borderless], backing: .buffered, defer: false ) isOpaque = false backgroundColor = .clear hasShadow = false level = .screenSaver collectionBehavior = [ .canJoinAllSpaces, .fullScreenAuxiliary, .stationary, .ignoresCycle ] ignoresMouseEvents = false acceptsMouseMovedEvents = true hidesOnDeactivate = false becomesKeyOnlyIfNeeded = false } // MARK: - Focus Prevention override var canBecomeKey: Bool { false } override var canBecomeMain: Bool { false } override var acceptsFirstResponder: Bool { false } override func makeKey() { } override func mouseDown(with event: NSEvent) { initialClickLocation = event.locationInWindow } override func mouseDragged(with event: NSEvent) { let current = event.locationInWindow let dx = current.x - initialClickLocation.x let dy = current.y - initialClickLocation.y let newOrigin = CGPoint( x: frame.origin.x + dx, y: frame.origin.y + dy ) setFrameOrigin(newOrigin) } func show<Content: View>(with view: Content) { let host = NSHostingView(rootView: view) host.autoresizingMask = [.width, .height] host.frame = contentLayoutRect contentView = host orderFrontRegardless() } func hide() { orderOut(nil) contentView = nil } } This is my Appkit Side code make a floating window, however, when the webcam preview is clicked, it makes it as the focus app and I have to click anywhere else to loose the focus to be able to use the rest of the windows.
Replies
0
Boosts
0
Views
736
Activity
Nov ’25
[macOS Sequoia] Using RegisterEventHotkey with option and shift modifiers doesn't working anymore
Hello. In my app, I use RegisterEventHotkey to implement global keyboard shortcuts to trigger actions. Up until macOS Sequoia, I was able to use a keyboard shortcut with option and shift as the modifiers, like option shift 2 (⌥ ⇧ 2). Now, on macOS Sequoia, using RegisterEventHotkey to register a hotkey with those exact modifiers (option and shift), regardless of the key, fails with the error -9868 (eventInternalErr). Is this a documented and wanted change, or is this a bug? Other modifier keys (just command, command option, command shift, command control, control shift, etc), all work. Any insight into this would be appreciated. (Feedback filed: FB15163561) Thank you, Matthias
Replies
22
Boosts
10
Views
16k
Activity
Nov ’25
macOS Tahoe: NSView -cacheDisplayInRect:toBitmapImageRep: Doesn't Work Unless View is Added to Window
Previously I was able to "snapshot" view that were not part of any window hierarchy using the following: NSImage *buttonImage = [NSImage imageWithSystemSymbolName:@"49.circle.fill" accessibilityDescription:nil]; NSButton *aButton = [NSButton buttonWithImage:buttonImage target:nil action:nil]; [aButton sizeToFit]; NSBitmapImageRep *rep = [aButton bitmapImageRepForCachingDisplayInRect:aButton.bounds]; if (rep == nil) { NSLog(@"Failed to get bitmap image rep."); return; } [aButton cacheDisplayInRect:aButton.bounds toBitmapImageRep:rep]; NSData *tiffData = rep.TIFFRepresentation; NSImage *snapShotOfImage = [[NSImage alloc]initWithData:tiffData]; Now on macOS Tahoe I get a non nil image, but the image is blank. However if I add aButton NSWindow's view hiearchy just before the call to -cacheDisplayInRect:toBitmapImageRep: I do get a proper image. Is this behavior intended or is this considered a bug? Is it documented anywhere that a view must be in a NSWindow for -cacheDisplayInRect:toBitmapImageRep: to work? Thanks
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
2
Boosts
0
Views
405
Activity
Nov ’25
Fetching Tinted Folder Icons in macOS Tahoe using Swift
In macOS Tahoe, users can tint folders or add symbols. But when trying to access that customized icon in Swift, the system always returns the default folder icon. NSWorkspace.shared.icon(forFile: url.path) try url.resourceValues(forKeys: [.effectiveIconKey]).effectiveIcon try url.resourceValues(forKeys: [.customIconKey]).customIconKey All of these give back the standard folder icon without any of the user-applied customization. So the question is: Is there any API or workaround in Swift to retrieve the actual customized folder icon (including tint and symbol) as displayed in Finder on macOS Tahoe?
Replies
1
Boosts
0
Views
450
Activity
Nov ’25