I created a simple application which displays a window with a sample text and I'm supposed to use an alert when the user chooses to close the application, if he presses ok in the alert the application will close, if he presses cancel it goes on.
So pretty simple code, I have a window class:
//
// MyWindow.h
// AppTest
//
// Created by sanya on 11/09/24.
//
#ifndef MyWindow_h
#define MyWindow_h
@interface Window : NSWindow
{
NSTextField* label;
}
- (instancetype)init;
- (BOOL)windowShouldClose:(id)sender;
@end
@implementation Window
-(instancetype)init
{
label = [[[NSTextField alloc] initWithFrame:NSMakeRect(5, 100, 290, 100)] autorelease];
[label setStringValue:@"Hello, World!"];
[label setBezeled:NO];
[label setDrawsBackground:NO];
[label setEditable:YES];
[label setSelectable:YES];
[label setTextColor:[NSColor colorWithSRGBRed:0.0 green:0.5 blue:0.0 alpha:1.0]];
[label setFont:[[NSFontManager sharedFontManager] convertFont:[[NSFontManager sharedFontManager] convertFont:[NSFont fontWithName:[[label font] fontName] size:45] toHaveTrait:NSFontBoldTrait] toHaveTrait:NSFontItalicTrait]];
[super initWithContentRect:NSMakeRect(0, 0, 300, 300) styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable backing:NSBackingStoreBuffered defer:NO];
[self setTitle:@"Hello world (label)"];
[[self contentView] addSubview:label];
[self center];
[self setIsVisible:YES];
return self;
}
- (BOOL)windowShouldClose:(id)sender
{
BOOL bClose = NO;
CFOptionFlags responseFlags = 0;
// Display the alert
CFUserNotificationDisplayAlert(
0,
kCFUserNotificationNoteAlertLevel,
NULL,
NULL,
NULL,
CFSTR("Alert Title"),
CFSTR("This is a message displayed in the alert."),
CFSTR("OK"),
CFSTR("Cancel"),
NULL,
&responseFlags
);
if (responseFlags == kCFUserNotificationDefaultResponse)
{
NSLog(@"User clicked OK");
bClose = YES;
}
else if (responseFlags == kCFUserNotificationAlternateResponse)
{
NSLog(@"User clicked Cancel");
}
if( bClose )
[NSApp terminate:sender];
return bClose;
}
@end
#endif /* MyWindow_h */
And in the main function I just initialize it:
int main(int argc, const char * argv[])
{
[NSApplication sharedApplication];
[[[[Window alloc] init] autorelease] makeMainWindow];
[NSApp run];
}
It seems to work but if click 'Cancel' on the dialog , xcode gives me the following warning:
CLIENT ERROR: TUINSRemoteViewController does not override -viewServiceDidTerminateWithError: and thus cannot react to catastrophic errors beyond logging them
So i'm obviously not doing this in the correct way, how can I fix this?
Also, any feedback on this code as a whole is highly appreciated.
AppKit
RSS for tagConstruct and manage a graphical, event-driven user interface for your macOS app using AppKit.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Hello,
I want to subclass NSDocumentController, but I could not find the information in Apple document how to subclass.
According to ChatGPT, it can be instantiated by [MyDocumentController sharedDocumentController]; before NSApplicationMain() as the following code. It seems working well in my test environment.
int main(int argc, const char * argv[]) {
[MyDocumentController sharedDocumentController];
NSApplicationMain(argc, argv);
}
But, I am not sure whether it is officially correct to instantiate so early (before calling NSApplicationMain).
Is there any official information what is correct way to instantiate subclass of NSDocumentController?
I have a SwiftUI View containing a PDFView from PDFKit (via NSViewRepresentable). When setting a new PDFDocument the view flashes briefly with the background color before displaying the new document.
Curiously the flashing is vastly reduced (but not eliminated) by calling layoutDocumentView() which should already be called from setDocument according to its documentation.
struct SheetView: NSViewRepresentable {
var pdf: PDFDocument?
func makeNSView(context: Context) -> PDFView {
let pdfView = PDFView()
pdfView.displaysPageBreaks = false
pdfView.displayMode = .singlePage
pdfView.pageShadowsEnabled = false
pdfView.autoScales = true
return pdfView
}
func updateNSView(_ pdfView: PDFView, context: Context) {
if pdf != pdfView.document {
pdfView.document = pdf
pdfView.layoutDocumentView() // reduces flashing but does not eliminate it
}
}
}
Hello,
while app icon is shown in 'Targets' app icon is not shown in 'alert panel'
What is wrong?
Best regards
Gerhard
I have an NSTextLayoutManager set up with NSTextContentStorage and NSTextContainer. To work out the height of the content, I call the method updateContentSizeIfNeeded() which contains the code
textLayoutManager.enumerateTextLayoutFragments(from: textLayoutManager.documentRange.endLocation, options: [.reverse, .ensuresLayout]) { layoutFragment in
height = layoutFragment.layoutFragmentFrame.maxY
return false
}
The first time this is called, it returns the correct height.
Then I add a new character to the start of the NSTextContentStorage like so
textContentStorage.performEditingTransaction {
storage.replaceCharacters(in: NSRange(location:0, length: 1), with: "a")
}
textLayoutManager.ensureLayout(for: textLayoutManager.documentRange)
textLayoutManager.textViewportLayoutController.layoutViewport()
updateContentSizeIfNeeded()
This time, the height returned is ~600px too big. The state of the NSTextLayoutFragment is set to layoutAvailable
The next time I add a character to textContentStorage using the same code above, the height returned is correct again.
I can work around this by calling enumerateTextLayoutFragments from the start of the document and not in reverse, then ignoring all fragments except the last one, but I don't know if that's the correct way to do it, or if I should be doing something else
Hello. What API or framework to use to simulate a mouse click on an iPad connected as an external display?
An iPad connected to the Mac via USB in a mode "Linked keyboard and mouse".
What is the way to simulate a mouse click at a specific coordinate at such a display?
So far I tried to simulate a click with CGEvent like so
if
let eventDown = CGEvent(mouseEventSource: source, mouseType: .leftMouseDown, mouseCursorPosition: point, mouseButton: .left),
let eventUp = CGEvent(mouseEventSource: source, mouseType: .leftMouseUp, mouseCursorPosition: point, mouseButton: .left)
{
eventDown.post(tap: .cghidEventTap)
usleep(500_000)
eventUp.post(tap: .cghidEventTap)
}
but it seems it does not work even on the main display. I set the point to the coordinate outside of the app window so that on a click another app should be focused but it does not happen on a simulated click.
I also tried to find a way to get a mouse coordinate on the external screen with addLocalMonitorForEvents. If I listen for the event
NSEvent.addLocalMonitorForEvents(matching: [.mouseMoved]) { event in
debugPrint("NSEvent.mouseLocation:", NSEvent.mouseLocation)
return event
}
it only works when the cursor is on the main screen and stops reporting as soon as the mouse enters the iPad.
So, any advice is welcomed on which direction I should look.
The new window resizing and placement feature of macOS Sequoia is not working in my application, and I don't know why. What's worse, I haven't consulted any relevant documents.
Topic:
UI Frameworks
SubTopic:
AppKit
I am trying to get the list of printers using NSPrinter.printerNames, but it doesn't return any items.
static func getPrinterList() -> [(name: String, isAvailable: Bool)] {
let printerNames = NSPrinter.printerNames
return printerNames.map { name in
let isAvailable = NSPrinter(name: name) != nil
return (name: name, isAvailable: isAvailable)
}
}
The printerNames is a empty string array.
I checked the settings for printers and screens, and there is a printer device listed.
I need to set something else?
I have two NSTextField as an accessoryView of NSSavePanel. When I try to change focus in between them with a caps lock on the whole panel will crash. This will also happen when NSTextField if focused with caps lock on and i press cmd+tab (app switching).
This happens on Sonoma + Sequoia beta. On top I have noticed editing NSTextField in accessoryView is completely broken on Sonoma and I can only edit it ONLY when the textfiled is using bindings.
I am trying to find a workaround for the caps lock indicator being displayed. The only idea I have ATM is to observe NSApp.windows and look for TUINSWindow and force close it when it's visible.
Is there any other workaround to prevent this crash?
https://youtu.be/BCVjZH7684U
Sample code:
import Cocoa
class ViewController: NSViewController {
let savePanel = NSSavePanel()
override func viewDidLoad() {
super.viewDidLoad()
let view = NSGridView(views: [[NSTextField(string: "111111")], [NSTextField(string: "22222222")]])
savePanel.accessoryView = view
}
override func viewWillAppear() {
savePanel.runModal()
}
}
Crash report:
Cannot remove an observer <TUINSCursorUIController 0x600001844340> for the key path "visible" from <NSSavePanel 0x10ff05200> because it is not registered as an observer.
(
0 CoreFoundation 0x000000019a2522ec __exceptionPreprocess + 176
1 libobjc.A.dylib 0x0000000199d36158 objc_exception_throw + 60
2 Foundation 0x000000019b30436c -[NSObject(NSKeyValueObserverRegistration) _removeObserver:forProperty:] + 628
3 Foundation 0x000000019b3040a4 -[NSObject(NSKeyValueObserverRegistration) removeObserver:forKeyPath:] + 136
4 TextInputUIMacHelper 0x0000000253d9e598 -[TUINSCursorUIController deactivate:] + 416
5 AppKit 0x000000019dbda3e4 -[NSTextInputContext deactivate] + 288
6 AppKit 0x000000019da3fff4 +[NSTextInputContext currentInputContext_withFirstResponderSync:] + 228
7 AppKit 0x000000019da4f084 -[NSView _setWindow:] + 692
8 AppKit 0x000000019db7d880 -[NSTextView(NSPrivate) _setWindow:] + 216
9 AppKit 0x000000019e4da778 __21-[NSView _setWindow:]_block_invoke.146 + 268
10 CoreAutoLayout 0x00000001a2aba588 -[NSISEngine withBehaviors:performModifications:] + 88
11 AppKit 0x000000019da4f4b4 -[NSView _setWindow:] + 1764
12 AppKit 0x000000019da7712c -[NSView removeFromSuperview] + 168
13 AppKit 0x000000019dc7c0e8 -[_NSKeyboardFocusClipView removeFromSuperview] + 56
14 AppKit 0x000000019dbc5474 -[NSWindow endEditingFor:] + 368
15 AppKit 0x000000019da770d0 -[NSView removeFromSuperview] + 76
16 AppKit 0x000000019dc7c0e8 -[_NSKeyboardFocusClipView removeFromSuperview] + 56
17 AppKit 0x000000019dc7be00 -[NSCell endEditing:] + 452
18 AppKit 0x000000019dc7b994 -[NSTextField textDidEndEditing:] + 264
19 CoreFoundation 0x000000019a1d2144 __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 148
20 CoreFoundation 0x000000019a2663d8 ___CFXRegistrationPost_block_invoke + 88
21 CoreFoundation 0x000000019a266320 _CFXRegistrationPost + 440
22 CoreFoundation 0x000000019a1a0678 _CFXNotificationPost + 768
23 Foundation 0x000000019b2bd2c4 -[NSNotificationCenter postNotificationName:object:userInfo:] + 88
24 AppKit 0x000000019dc7b5fc -[NSTextView(NSSharing) resignFirstResponder] + 668
25 AppKit 0x000000019db2ca80 -[NSWindow _realMakeFirstResponder:] + 196
26 AppKit 0x000000019dcc1764 -[NSWindow _makeParentWindowHaveFirstResponder:] + 76
27 ViewBridge 0x00000001a296c8c0 -[NSAccessoryViewWindow makeFirstResponder:] + 80
28 AppKit 0x000000019dbdbb9c -[NSWindow(NSEventRouting) _handleMouseDownEvent:isDelayedEvent:] + 3148
29 AppKit 0x000000019db67504 -[NSWindow(NSEventRouting) _reallySendEvent:isDelayedEvent:] + 288
30 AppKit 0x000000019db67210 -[NSWindow(NSEventRouting) sendEvent:] + 284
31 ViewBridge 0x00000001a296cecc -[NSAccessoryViewWindow sendEvent:] + 64
32 AppKit 0x000000019e2304f0 -[NSApplication(NSEventRouting) sendEvent:] + 1604
33 AppKit 0x000000019dc6df6c -[NSApplication _doModalLoop:peek:] + 276
34 AppKit 0x000000019dc6ce38 __35-[NSApplication runModalForWindow:]_block_invoke_2 + 56
35 AppKit 0x000000019dc6cde4 __35-[NSApplication runModalForWindow:]_block_invoke + 108
36 AppKit 0x000000019dc6c6b0 _NSTryRunModal + 100
37 AppKit 0x000000019dc6c570 -[NSApplication runModalForWindow:] + 292
38 AppKit 0x000000019e690490 -[NSSavePanel runModal] + 340
39 SavePanelAccessory 0x0000000100435ad4 $s18SavePanelAccessory14ViewControllerC14viewWillAppearyyF + 60
40 SavePanelAccessory 0x0000000100435b0c $s18SavePanelAccessory14ViewControllerC14viewWillAppearyyFTo + 36
41 AppKit 0x000000019db387f4 -[NSViewController _sendViewWillAppear] + 32
42 AppKit 0x000000019db386bc -[NSViewController _windowWillOrderOnScreen] + 80
43 AppKit 0x000000019e4e7b38 -[NSView _windowWillOrderOnScreen] + 56
44 AppKit 0x000000019e4e7ba4 -[NSView _windowWillOrderOnScreen] + 164
45 AppKit 0x000000019db38570 -[NSWindow _doWindowWillBeVisibleAsSheet:] + 40
46 AppKit 0x000000019e4fc418 -[NSWindow _reallyDoOrderWindowAboveOrBelow:] + 1028
47 AppKit 0x000000019e4fcfec -[NSWindow _reallyDoOrderWindow:] + 64
SHORTENED
Topic:
UI Frameworks
SubTopic:
AppKit
Our MacOS application has a single window which is occupied by an NSView-derived view. It's been working for the last ten years or so, but when using the Sonoma beta, window updates are badly broken.
We rely on using setNeedsDisplayInRect to redisplay any portions of the view that need to be redisplayed, but no matter how small a rectangle we specify, the entire window is repainted with the background colour before our drawRect implementation is called. We already provide an overload of isOpaque in our view which returns true, and in the past this was effective for suppressing the background fill, but it no longer seems to work (although I can confirm that it is still called along the way).
I've attached an image that shows an example of how a sample window looks after resizing (which is correct) and then what it looks like after using setNeedsDisplayInRect to invalidate the region occupied by the button in the centre. I've explicitly set the NSWindow background colour to blue to make it more obvious :
Is it still possible to inhibit the background fill? Repainting the entire view for every update is not really an option for us, for performance reasons
I need to draw an attributed string into a given rectangle. The string's height should be the same as the rectangle's height. This should work with any font a user chooses. To make it a bit more complicated, the string should also fill the rect if it consists only of uppercase characters or only of lowercase characters.
I am using NSLayoutManager to find the "best" font size for the selected font and the given recht and it works quite good with some fonts but with others it doesn't. Seems like the computed font size is always a bit too small and for some fonts it seems like the baseline must be corrected. Unfortunately I didn't find a way to calculate a baseline offset that really works with any font. I attached some sample images showing the issue.
Just posting this to make sure I am not running in the complete wrong direction. Any help would be highly appreciated. Thanks!
Our app supports only portrait mode. And in some cases, the status bar moves horizontally, as shown in the video below. We have confirmed that this problem does not appear in OS versions 15.3.1 and lower. The problem occurs on OS 16 and 17.
https://youtu.be/CiR5LcoBI5c
At the point when the problem appears, the code simply subscribes to data through the interval scheduler. The code is below: At that point, set autoUpdate to true.
private let autoUpdateTimer = Observable<Int>.interval(.seconds(20), scheduler: MainScheduler.asyncInstance)
private var autoUpdate = BehaviorRelay<Bool>(value: false)
autoUpdateTimer
.withLatestFrom(autoUpdate)
.filter { $0 }
.withLatestFrom(Observable.combineLatest(deviceSeq,currentChannel,channel)
.map { ($0.0, $0.1, 1, $0.2?.property?.unitCount ?? 1) }
.flatMap(dependency.usecase.pubAutoStatus)
.subscribe().disposed(by: disposeBag)
I would appreciate any feedback on how I can resolve this.
Topic:
UI Frameworks
SubTopic:
AppKit
I am use XCode 15.2 and macOS SDK 14.2.
I placed an NSView inside the NSClipView of an NSScrollView, the NSView is smaller than the NSClipView, always centered.
On Ventura, regardless of whether clipsToBounds is set, the bounds and visibleRect of the NSView are the same.
However, on Sonoma, even after overriding
-(BOOL)clipsToBounds
{
return YES;
}, the bounds is correct, but the visibleRect (the red rect) is still the same size as the NSClipView, results in the text is not clipped.
Am I missing something or doing something wrong?
How can I make the visibleRect of the NSView consistent with its bounds?
Topic:
UI Frameworks
SubTopic:
AppKit
here's my case, i develop a control widget, user can push a controlwidget to play music without open the app.
i bind a AudioPlaybackIntent to the widget. when user click the widget, the app will receive the intent and start to play music.
it works perfect when app running in background or foreground. but when app not launched, the respond is too slow, it takes several seconds to start play music.
is there any way to make the respond faster when app not launched? if i want to do something when app not launched, what should i do?
If anyone there is familiar with Cocoa, can you please help with the following issue: How to make the NSWindow resize based on the contentView? Here is a video of the problem: https://drive.google.com/file/d/19LN98xdF9OLcqRZhMJsGGSa0dgMvj_za/view?usp=sharing
Thanks!
This issue happens in my app and I don't know why, I cannot get even useful info from stack. it's all about AppKit and HIToolBox or CoreFoundation.
I initially suspect it might be related to NSTimer. However I think this wouldn't cause such a crash. I am currently out of ideas and unable to provide more detailed and effective information (if I could, that would be great, and I also hope to have it).
I search Apple Doc and it tell me NSInternalInconsistencyException occurs when an internal assertion fails and implies an unexpected condition within the called code. So I want to get some clues from you why I encounter such an issue.
@interface MyApp () {
scoped_refptr<base::SequencedTaskRunner> task_runner_;
}
@implementation MyApp
//...
- (void)start {
// ...
self.timer = [NSTimer
scheduledTimerWithTimeInterval:60 // call every 60 sec
target:self
selector:@selector(logAndKill:)
userInfo:info
repeats:YES];
- (void)logAndKill {
if (needLog) {
// ...
} else {
task_runner_->PostTask(FROM_HERE, base::BindOnce(^() {
[self.timer invalidate];
self.timer = nil;
}));
Topic:
UI Frameworks
SubTopic:
AppKit
Dear all,
I'm building my first MacOs app.
I've created my app icon and add it to AppIcon folder, but when I'm building the application the icon shows in the dock of the screen with no rounded borders like all the other apps.
I'm attaching here the icon and as you can see it has sharp edges. It is the same way in which it shows on the dock.
Why? Has anybody experienced the same?
Thanks for the support in advance,
A.
i init a CPAlertTemplate with a CPAlertAction, on iOS17, action can called by button click, but on iOS18, action can not be called by button click.
so i can't dissmiss the alert by button click.
We are developing a lightweight VPN client inside a daemon process that will run even when no user session is active on machine. The lightweight VPN runs in machine context and does not require user session. We would like to display some basic diagnosis information about our lightweight client on macOS login window before user is logged into their machine (in case users need that).
So, is it possible to display a UI window on login screen with some basic info that user can interact with. If yes, where can I get started?
Please note, this is not an authorization plugin. We are just wanting to display info about our process that runs a lightweight VPN client on macOS login screen.
I have a textfield in accessory view of NSSavePanel. For user convenience there are default actions supported natively by macOS (such as pressing Enter, keyEquivalent). However this doesn't work for enter under Sonoma. Escape key works. Is enter keypress dangerous for malicious actors so it's not supported? I have workaround below but I am not confident if I am not violating sandbox (future proof).
Original code demonstrating the issue:
class ViewController: NSViewController, NSTextFieldDelegate, NSControlTextEditingDelegate {
let savePanel = NSSavePanel()
override func viewDidLoad() {
super.viewDidLoad()
let customView = NSView()
let textField = NSTextField(string: "11111111")
textField.delegate = self // to get focus using tab keypress
savePanel.accessoryView = textField
}
override func viewWillAppear() {
savePanel.runModal()
}
}
Workaround:
// variable set to true in delegate method controlTextDidEndEditing
var didUseTextFieldWithEnterPressed = false
override func performKeyEquivalent(with event: NSEvent) -> Bool {
if #unavailable(macOS 14) {
return super.performKeyEquivalent(with: event)
}
guard let panel, didUseTextFieldWithEnterPressed == true, event.type == .keyDown &&
(event.keyCode == UInt16(kVK_Return) || event.keyCode == UInt16(kVK_ANSI_KeypadEnter)) else {
return super.performKeyEquivalent(with: event)
}
return panel.performKeyEquivalent(with: event)
}