I've received some reports from users of my macOS app that the application quits when putting their Mac to sleep after hiding all windows.
The NSApplicationDelegate implements applicationShouldTerminateAfterLastWindowClosed and returns true. However this method is called even though there are still windows open.
Unfortunately I'm not able to reproduce the issue, but here are the steps to reproduce according to the user:
Open app (single NSWindow visible)
Press Command-H to hide the single window
Put Mac to sleep
The app is terminated when the Mac wakes. These steps have been confirmed by a user in Safe Mode, so I expect no interference of other applications (macOS 15.1.1).
When this happens the application logs show that applicationShouldTerminateAfterLastWindowClosed is called when the Mac goes to sleep. But the main NSWindow is still open (yet hidden). The close() method on NSWindow is not called before applicationShouldTerminateAfterLastWindowClosed.
Order of events:
NSApplicationDelegate.applicationWillHide
NSApplicationDelegate.applicationWillResignActive
[...]
NSApplicationDelegate.applicationShouldTerminateAfterLastWindowClosed
NSApplicationDelegate.applicationShouldTerminate
NSApplicationDelegate.applicationWillTerminate
NSWindow.close
I assumed that applicationShouldTerminateAfterLastWindowClosed is only called after all windows are closed. Is that assumption incorrect?
Does a user-hidden NSWindow count as a closed window?
For me (and other users) the API works as expected and the app stays running when the app is hidden as the Mac sleeps. applicationShouldTerminateAfterLastWindowClosed is not called until all windows are actually closed.
AppKit
RSS for tagConstruct and manage a graphical, event-driven user interface for your macOS app using AppKit.
Post
Replies
Boosts
Views
Activity
I am trying to carry out repairs on my computer, it is an old MacBook Pro which I really appreciate, and it works very well, before attempting a hardware repair, I am exhausting all the software resources, in one of its support forums I found a supposed solution, I just can't see the assigned plist, but I see that it appears in the example as root within xcode, could you help me with what the steps would be to enter root mode and thus be able to make the relevant adjustment , I attach the link to the example.
thank you so much
https://discussions.apple.com/thread/3114550?sortBy=rank)
The example can be found in Grant Bennet-Alder coment
I have a MacOs AppKit app. This app we are developing for examination purposes. We dont want the user to screen record and also to take screen shot.
We created a window and set the sharingType to none. also we have set window.level to CGShieldingWindowLevel()
Below is the code
if let window = NSApp.windows.first {
window.title = "Test"
window.sharingType = .none // Disable screen capture and recording
window.level = NSWindow.Level(rawValue: Int(CGShieldingWindowLevel())) //
}
As per documentation the windows should be excluded from screen capture and also recording
But the window is excluded only from screen capture and not from screen recording. Please give us a solution to prevent screen recording in MacOs native app.
When putting a TextField into a TableColumn, and while editing, the text exceeds the column width - any way to automatically resize the width to match the entered text ?
I use IKSaveOptions to add an accessory view to an NSSavePanel to give the user choice of the image file type (etc) used to save a file. I limit the available file type choices in the accessory's menu by specifying a delegate object that offers the saveOptions:shouldShowUTType: method.
Historically, my delegate was called repeatedly (for many file types) so, for those not supported by my code, I was able to omit them from the menu. This is expected behaviour from my interpretation of the documentation for saveOptions:shouldShowUTType:
As of Ventura 13.1, the delegate was not called at all; instead, the entire (or at least a long) list of options was offered in the panel. Running the same build of my code on Catalina 10.15.7 still had the historical behaviour.
In Sonoma (14.0) the delegate was called exactly once (for JPEG). This behaviour persists in Sequoia 15.1.1 .
I have used test code and breakpoints to ensure that I pass a valid reference to my delegate and to inspect when (if) it is called.
If there is some (new?) pre-condition for the accessory's use needed on Ventura and later, or a workaround, I would be grateful to be pointed to it.
Hi,
On macOS, there seems to be a NSTableViewDiffableDataSource and an NSCollectionViewDiffableDataSource, but there seems to be nothing for NSOutlineView. Is it possible to somehow use NSTableViewDiffableDataSource with NSOutlineView that I'm missing?
If not, is it possible to use NSTableView with NSTableViewDiffableDataSource to show a 'table' with section headers?
When I generate a dial through code, it prompts the following content:
code:
CLKWatchFaceLibrary * lib = [[CLKWatchFaceLibrary alloc] init];
[lib addWatchFaceAtURL:url completionHandler:^(NSError * _Nullable error) {
}];
result:
Complex functions are not available
How to fix it? Make it usable, Thank you~
In MacOS app I present modally NSTableView.
The table is created in IB and its data and functionality are handled in corresponding NSViewController.
As long as the positioning of modally presented table is left to the system, the tableview is placed in the center of the presenting view controller and everything works fine.
But if I apply NSLayoutConstraints to position it as I need for visual design reasons, the table stops responding to mouse clicks.
Here's the code inside the presenting view controller:
bookmarks_TVC = Bookmarks_TVC()
bookmarks_TVC.view.translatesAutoresizingMaskIntoConstraints = false
self.present(bookmarks_TVC, animator: ModalPresentationAnimator())
NSLayoutConstraint.activate([
self.bookmarks_TVC.view.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant:410),
self.bookmarks_TVC.view.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 170)
])
Once again, without NSLayoutConstraints the table responds as expected. Once the constraints are added, it becomes unresponsive.
Thanks in advance for any helpful suggestions.
I properly copy a scrFile to a dstFile with
mManager = [NSFileManager defaultManager];
[mManager copyItemAtPath:srcPath toPath:dstPath error:&error];
but on "some destination disks" the dstFile gets a modificationDate with truncated milliseconds. For instance, with this format
"yyyy.MM.dd - HH:mm:ss:SSS" I visualize
srcDate = 2024.11.03 - 12:42:35:772
dstDate = 2024.11.03 - 12:42:35:000
After the copyItemAtPath I even unsuccessfully tried to set the dstFile modificationDate this way
NSMutableDictionary *dstAttrs = [NSMutableDictionary dictionaryWithDictionary:[mManager attributesOfItemAtPath:dstPath error:nil]];
[dstAttrs setObject:srcDate forKey:NSFileModificationDate];
[mManager setAttributes:dstAttrs ofItemAtPath:dstPath error:nil];
Again, the dstDate is 2024.11.03 - 12:42:35:000.
I unsuccessfully tried even
FSSetCatalogInfo(&dstRef, fsInfo, &srcFsCatInfo);
No way. I noticed that the destination disk is an USB External Physical Volume, Mac OS Extended (Journaled) with "Ignore Ownership on this volume" on. Could this flag be the cause of the trouble? Shouldn't this flag regard only the files ownership?
This issue brings another trouble. Since the srcDate and the dstDate are not equal, my macOS app performing a backup, copies the srcFile to the dstFile again and again.
To workaround the trouble, I actually compare srcDate with dstDate after truncating their milliseconds. But I guess this is not a good practice.
Any idea on how to fix this trouble? Thanks.
P.S. I attach here the disk info
Disk_Info.txt
So I'm following this code here where I'm using a tableview to display the files contained in a folder along with a group cell to display the name of the current folder:
Here's my tableView:isGroupRow method: method which basically turns every row with the folder name into a group row (which is displayed in red in the previous image ).
-(BOOL)tableView:(NSTableView *)tableView isGroupRow:(NSInteger)row
{
DesktopEntity *entity = _tableContents[row];
if ([entity isKindOfClass:[DesktopFolderEntity class]])
{
return YES;
}
return NO;
}
and here's my tableView:viewForTableColumn:row: method where I have two if statements to decide whether the current row is a group row (meaning it's a folder) or an image:
-(NSView*)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row;
{
DesktopEntity *entity = _tableContents[row];
if ([entity isKindOfClass:[DesktopFolderEntity class]])
{
NSTextField *groupCell = [tableView makeViewWithIdentifier:@"GroupCell" owner:self];
[groupCell setStringValue: entity.name];
[groupCell setFont:[NSFont fontWithName:@"Arial" size:40]];
[groupCell setTextColor:[NSColor magentaColor]];
return groupCell;
}
else if ([entity isKindOfClass:[DesktopImageEntity class]])
{
NSTableCellView *cellView = [tableView makeViewWithIdentifier:@"ImageCell" owner:self];
[cellView.textField setStringValue: entity.name];
[cellView.textField setFont:[NSFont fontWithName:@"Impact" size:20]];
[cellView.imageView setImage: [(DesktopImageEntity *)entity image]];
return cellView;
}
return nil;
}
Now, if the current row is an image, I change its font to Impact with a size of 40 and that works perfectly, the problem here is with the first IF statement, for a group row I wanted to change the font size to arial with a size of 40 with a magenta color but for some reason I can only get the color to work:
You can see that my changes to the font size didn't work here, what gives?
How can I change the font size for the group row ?
import Cocoa
@available(macOS 10.13, *)
let imagePboardType = NSPasteboard.PasteboardType.fileURL
class DragSourceView: NSImageView {
weak var dragSourceDelegate: NSDraggingSource?
override func mouseDown(with event: NSEvent) {
//拖放数据定义
let pasteboardItem = NSPasteboardItem()
//设置数据的Provider
if #available(macOS 10.13, *) {
pasteboardItem.setDataProvider(self, forTypes: [NSPasteboard.PasteboardType.fileURL])
} else {
// Fallback on earlier versions
}
//拖放item
let draggingItem = NSDraggingItem(pasteboardWriter: pasteboardItem)
draggingItem.draggingFrame = NSRect(x: 100 , y: 10, width: 100, height: 100)
//拖放可视化图象设置
draggingItem.imageComponentsProvider = {
let component = NSDraggingImageComponent(key: NSDraggingItem.ImageComponentKey.icon)
component.frame = NSRect(x: 0, y: 0, width: 16, height: 16)
component.contents = NSImage(size: NSSize(width: 32,height: 32), flipped: false, drawingHandler: { [unowned self] rect in {
self.image?.draw(in: rect)
return true
}()
}
)
return [component]
}
//开始启动拖放sesson
self.beginDraggingSession(with: [draggingItem], event: event, source: self.dragSourceDelegate!)
}
}
extension DragSourceView: NSPasteboardItemDataProvider {
func pasteboard(_ pasteboard: NSPasteboard?, item: NSPasteboardItem, provideDataForType type: NSPasteboard.PasteboardType) {
// let data = self.image?.tiffRepresentation
let data = "/Users/slowdony/Desktop/640.jpeg"
let dataUrl = data.data(using: String.Encoding(rawValue: NSUTF8StringEncoding))!
item.setData(dataUrl, forType: type)
}
}
import Cocoa
class ViewController: NSViewController {
@IBOutlet weak var sourceView: DragSourceView!
override func viewDidLoad() {
super.viewDidLoad()
self.sourceView.dragSourceDelegate = self
}
}
extension ViewController: NSDraggingSource {
//返回拖放操作类型
func draggingSession(_ session: NSDraggingSession, sourceOperationMaskFor context: NSDraggingContext) -> NSDragOperation {
if (context == .outsideApplication){
return .copy
}
else{
return .generic
}
}
//开始拖放代理回调
func draggingSession(_ session: NSDraggingSession, willBeginAt screenPoint: NSPoint) {
print("draggingSession beginAt \(screenPoint)")
}
//拖放鼠标移动时的代理回调
func draggingSession(_ session: NSDraggingSession, movedTo screenPoint: NSPoint) {
print("draggingSession movedTo \(screenPoint)")
}
//结束拖放代理回调
func draggingSession(_ session: NSDraggingSession, endedAt screenPoint: NSPoint, operation: NSDragOperation) {
print("draggingSession endedAt \(screenPoint)")
}
}
I am dragging an image to the desktop through the above code, failed, help
Developing on Monterey 12.7.5
I'm having trouble with updating subitems on NSToolbarItemGroup when selecting the item directly from the NSToolbar items array.
I select the group item off the items array on the toolbar, and then call setSubitems: on the item, with a new array of NSToolbarItems. The group item disappears from the toolbar. It seems to leave a blank invisible item in the toolbar taking up space. I can't manually reinsert the item into the toolbar until I drag out the blank item, then drag back in the real item. Once dragged back in from the palette it displays correctly.
The workaround I've come up with is to remove the item with NSToolbar removeItemAtIndex: and reinsert it with NSToollbar insertItemWithItemIdentifier:atIndex:. This works to update the subitems.
Every other toolbar item property that I've tried has been able to update the item directly in the toolbar. It's only the group item's subitems that don't want to update correctly.
Is there a correct way to do this that I'm missing? Calling [toolbar validateVisibleItems] didn't seem to help.
I am using the window.level set to .floating as described here:
https://developer.apple.com/documentation/appkit/nswindow/level
The setting itself works okay. However, in a multi monitor setup, the floating window is appearing on both the screens.
How can I prevent this? My users report that before macOS Sonoma, this used to not happen. Has this behaviour changed? How can I revert back to the old behaviour?
I made an account on this site for the sole reason to post this.
I can not stand the IOS 18 photo app, to put it bluntly its sucks, it's made the app unusable.
I was nice, I'd thought I'd give it a month or two but no, it still sucks.
I wish I could uninstall IOS 18 solely cause of it.
I hate the UI, its utterly unintuitive.
I'm seeing a discrepancy in the metrics of the "New York" system font returned from various Macs. Here's a sample (works well in Playgrounds):
import Cocoa
let font = NSFont(descriptor: .preferredFontDescriptor(forTextStyle: .body).withDesign(.serif)!, size: NSFont.systemFontSize)!
print("\(font.fontName) \(font.pointSize)")
print("ascender: \(font.ascender)")
let layoutManager = NSLayoutManager()
print("lineHeight: \(layoutManager.defaultLineHeight(for: font))")
When I run this on multiple Macs, I get two types of different results. Some – most Macs – report this:
.NewYork-Regular 13.0
ascender: 12.3779296875
lineHeight: 16.0
However, when I run on my own Mac (and also on the one of a colleague), I get this instead:
.NewYork-Regular 13.0
ascender: 14.034145955454255
lineHeight: 19.0
It's clearly the same font in the same point size. Yet the font has different metrics, causing a layout manager to also compute a significantly different line height.
So far I've found out that neither CPU generation/architecture nor macOS version seem to play a role. This issue has been reproducible since at least macOS 14. Having just migrated to a new Mac, the issue is still present.
This does not affect any other system or commonly installed font. It's only New York (aka the serif design).
So I assume this must be something with my setup. Yet I have been unable to find anything that may cause this. Anybody have some ideas? Happy to file a bug report but wanted to check here first.
I am trying to understand why I am seeing crash reports for my code that creates a view from a NIB like the code below. The crash occurs when referencing contentView which should have been bound when the NIB was loaded.
Am I missing something here other than checking the result of the loadNibNamed function call?
class MyView: NSView {
@IBOutlet var contentView: NSView!
init() {
super.init(frame: NSRect(x: 0, y: 0, width: 84.0, height: 49.0))
commonInit()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func commonInit() {
Bundle.main.loadNibNamed("MyView", owner: self, topLevelObjects: nil)
translatesAutoresizingMaskIntoConstraints = false
contentView.translatesAutoresizingMaskIntoConstraints = false
addSubview(contentView)
contentView.frame = self.bounds
}
I have an old Objective-C app that has been running for several years. The last compilation was in February 2024. I just upgraded to Sequoia 15.1.
The app has four subviews on its main view. When I run the app only the subview that was the last one instantiated is visible. I know the other subviews are there, because a random mouse click in one invisible view causes the expected change in the visible view.
What changed in 15.1 to cause this?
I am creating an iOS app to install on legacy iPads running iOS 9 and up, using XCode 13.4.1 which is the latest version that will support iOS below 11. The app is working fine but I just added a QuickLook Preview extension, and on iOS 10.3.1 it will not install due to the following error:
This app contains an app extension that specifies an extension point identifier that is not supported on this version of iOS for the value of the NSExtensionPointIdentifier key in its Info.plist. Domain: com.apple.dt.MobileDeviceErrorDomain Code: -402653007
The NSExtensionPointIdentifier key in Info.plist is set by XCode automatically to "com.apple.quicklook.preview".
I want to set the iOS Deployment Target to the lowest iOS version that will support this configuration. The documentation does not provide any guide as to which specific NSExtensionPointIdentifier keys are compatible with which iOS version. It just says 8+ for the whole list. Trial-and-error is limited by availability of legacy Simulators.
If anyone can point to documentation that indicates which iOS is supported by which NSExtensionPointIdentifier key com.apple.quicklook.preview, I would be very grateful. Thanks
(I understand about lack of App Store support etc, this is an app for my use on old iPads)
This is a post down memory lane for you AppKit developers and Apple engineers...
TL;DR:
When did the default implementation of NSViewController.loadView start making an NSView when there's no matching nib file? (I'm sure that used to return nil at some point way back when...)
If you override NSViewController.loadView and call [super loadView] to have that default NSView created, is it safe to then call self.view within loadView?
I'm refactoring some old Objective-C code that makes extensive use of NSViewController without any use of nibs. It overrides loadView, instantiates all properties that are views, then assigns a view to the view controller's view property. This seems inline with the documentation and related commentary in the header. I also (vaguely) recall this being a necessary pattern when not using nibs:
@interface MyViewController: NSViewController
// No nibs
// No nibName
@end
@implementation MyViewController
- (void)loadView {
NSView *hostView = [[NSView alloc] initWithFrame:NSZeroRect];
self.button = [NSButton alloc...];
self.slider = [NSSlider alloc...];
[hostView addSubview:self.button];
[hostView addSubview:self.slider];
self.view = hostView;
}
@end
While refactoring, I was surprised to find that if you don't override loadView and do all of the setup in viewDidLoad instead, then self.view on a view controller is non-nil, even though there was no nib file that could have provided the view. Clearly NSViewController has realized that:
There's no nib file that matches nibName.
loadView is not overridden.
Created an empty NSView and assigned it to self.view anyways.
Has this always been the behaviour or did it change at some point? I could have sworn that if there as no matching nib file and you didn't override loadView, then self.view would be nil.
I realize some of this behaviour changed in 10.10, as noted in the header, but there's no mention of a default NSView being created.
Because there are some warnings in the header and documentation around being careful when overriding methods related to view loading, I'm curious if the following pattern is considered "safe" in macOS 15:
- (void)loadView {
// Have NSViewController create a default view.
[super loadView];
self.button = [NSButton...];
self.slider = [NSSlider...];
// Is it safe to call self.view within this method?
[self.view addSubview:self.button];
[self.view addSubview:self.slider];
}
Finally, if I can rely on NSViewController always creating an NSView for me, even when a nib is not present, then is there any recommendation on whether one should continue using loadView or instead move code the above into viewDidLoad?
- (void)viewDidLoad {
self.button = [NSButton...];
self.slider = [NSSlider...];
// Since self.view always seems to be non-nil, then what
// does loadView offer over just using viewDidLoad?
[self.view addSubview:self.button];
[self.view addSubview:self.slider];
}
This application will have macOS 15 as a minimum requirement.
When I upgraded to Sequoia 15.1, an app that worked fine under OS 14 stopped working. Out of 4 views on the main screen, only 1 is visible. Yet, if I click where another view should be, I get the expected action so the views are there, just not visible. Only I can't see where I am clicking!
I had to upgrade to Xcode 16 to recompile the app and run it in Debug mode. When I do, I get the following:
NSBundle file:///System/Library/PrivateFrameworks/MetalTools.framework/ principal class is nil because all fallbacks have failed.
Can't find or decode disabled use cases.
applicationSupportsSecureRestorableState
FWIW - the only view that actually shows up is the last subview added to the main view.