Summary
macOS 14 Sonoma adds the "Text Size" setting under Settings -> Accessibility -> Display. This is similar to the "Text Size" setting that has been in iOS for quite some time.
Many Apple apps automatically adjust the size of their text based on this setting. This includes Xcode, Settings, Finder, Mail, Notes, and others. Apps like Xcode and Settings only change the text in sidebars while the other apps change text throughout the app.
Question
My question is how to respond to this setting in my own macOS app?
Research
I've searched the AppKit documentation. I've searched WWDC videos. I've searched the Apple developer forums. There's no mention of how this is done that I have seen.
Here on SO I've seen:
- macOS project’s fonts are not scaling but this doesn't address my more specific question.
- Dynamic font size for NSTextField on macOS but it has no responses and it is focused only on
NSTextField. - How to make font size customizable in a macOS app but this is about supporting an app-specific text size, not using the system setting.
Experiments
I've created a native macOS app using AppKit. I've added an NSTextField and an NSTextView and set the fonts to a text style such as "Title 1". Changing the setting does not automatically change the displayed font size in the app.
I've created a SwiftUI app and added a native macOS build. I setup a ContentView with some Text using Text("This is some text").font(.title). Changing the setting does not automatically change the displayed font size in the app.
I have an iOS app built for macOS using Mac Catalyst. The iOS version of the app automatically adjusts its text when the "Text Size" setting is changed in the iOS Settings app. The macOS version of the app does not change at all when the "Text Size" setting is changed in the macOS Settings app.
In the native AppKit app I tried the following code in the AppDelegate:
NSWorkspace.shared.notificationCenter.addObserver(forName: nil, object: nil, queue: nil) { note in
print(note)
}
NotificationCenter.default.addObserver(forName: nil, object: nil, queue: nil) { note in
print(note)
}
Neither of these generated any output when the "Text Size" setting was changed. Under iOS/UIKit, you get a UIContentSizeCategory.didChangeNotification notification.
As a shot in the dark I setup the AppKit app with my own custom NSApplication subclass and added the following:
class Application: NSApplication {
override func sendEvent(_ event: NSEvent) {
print("event \(event)")
super.sendEvent(event)
}
override func sendAction(_ action: Selector, to target: Any?, from sender: Any?) -> Bool {
print("action: \(action)")
return super.sendAction(action, to: target, from: sender)
}
}
Neither of these produced output when the "Text Size" setting was changed.
Summary
I'm at a loss at this point. What code is needed to allow a macOS app to respond to changes to the "Text Size" setting? My immediate need is with an iOS/UIKit app built for macOS with Mac Catalyst but I'm fine with solutions in native AppKit or even SwiftUI. Code can be in either Swift or Objective-C.