NSApplication object manages an app’s main event loop in addition to resources used by all of that app’s objects.
- macOS 10.10+
Every app must have exactly one instance of
NSApplication (or a subclass of
NSApplication). Your program’s
main() function should create this instance by invoking the
shared() class method. After creating the
NSApplication object, the
main() function should load your app’s main nib file and then start the event loop by sending the
NSApplication object a
run() message. If you create an Application project in Xcode, this
main() function is created for you. The
main() function Xcode creates begins by calling a function named
NSApplicationMain(), which is functionally similar to the following:
shared() class method initializes the display environment and connects your program to the window server and the display server. The
NSApplication object maintains a list of all the
NSWindow objects the app uses, so it can retrieve any of the app’s
NSView objects. The
shared() method also initializes the global variable
NSApp, which you use to retrieve the
shared() only performs the initialization once; if you invoke it more than once, it simply returns the
NSApplication object it created previously.
NSApplication object performs the important task of receiving events from the window server and distributing them to the proper
NSApp translates an event into an
NSEvent object, then forwards the
NSEvent object to the affected
NSWindow object. All keyboard and mouse events go directly to the
NSWindow object associated with the event. The only exception to this rule is if the Command key is pressed when a key-down event occurs; in this case, every
NSWindow object has an opportunity to respond to the event. When an
NSWindow object receives an
NSEvent object from
NSApp, it distributes it to the objects in its view hierarchy.
NSApplication is also responsible for dispatching certain Apple events received by the app. For example, macOS sends Apple events to your app at various times, such as when the app is launched or reopened.
NSApplication installs Apple event handlers to handle these events by sending a message to the appropriate object. You can also use the
NSAppleEventManager class to register your own Apple event handlers. The
applicationWillFinishLaunching(_:) method is generally the best place to do so. For more information on how events are handled and how you can modify the default behavior, including information on working with Apple events in scriptable apps, see How Cocoa Applications Handle Apple Events in Cocoa Scripting Guide.
NSApplication class sets up
@autorelease block during initialization and inside the event loop—specifically, within its initialization (or
run() methods. Similarly, the methods AppKit adds to
@autorelease blocks during the loading of nib files. These
@autorelease blocks aren’t accessible outside the scope of the respective
NSBundle methods. Typically, an app creates objects either while the event loop is running or by loading objects from nib files, so this lack of access usually isn’t a problem. However, if you do need to use Cocoa classes within the
main() function itself (other than to load nib files or to instantiate
NSApplication), you should create an
@autorelease block to contain the code using the classes.
The Delegate and Notifications
You can assign a Delegation to
NSApp. The delegate responds to certain messages on behalf of
NSApp. Some of these messages, such as
application(_:openFile:), ask the delegate to perform an action. Another message,
applicationShouldTerminate(_:), lets the delegate determine whether the app should be allowed to quit. The
NSApplication class sends these messages directly to its delegate.
NSApp also posts notifications to the app’s default notification center. Any object may register to receive one or more of the notifications posted by
NSApp by sending the message
addObserver(_:selector:name:object:) to the default notification center (an instance of the
NSNotificationCenter class). The delegate of
NSApp is automatically registered to receive these notifications if it implements certain delegate methods. For example,
NSApp posts notifications when it is about to be done launching the app and when it is done launching the app (
NSApplicationDidFinishLaunching). The delegate has an opportunity to respond to these notifications by implementing the methods
applicationDidFinishLaunching(_:). If the delegate wants to be informed of both events, it implements both methods. If it needs to know only when the app is finished launching, it implements only
NSApplication interacts with the system services architecture to provide services to your app through the Services menu.
You rarely should find a real need to create a custom
NSApplication subclass. Unlike some object-oriented libraries, Cocoa does not require you to subclass
NSApplication to customize app behavior. Instead it gives you many other ways to customize an app. This section discusses both some of the possible reasons to subclass
NSApplication and some of the reasons not to subclass
To use a custom subclass of
NSApplication, simply send
shared() to your subclass rather than directly to
NSApplication. If you create your app in Xcode, you can accomplish this by setting your custom app class to be the principal class. In Xcode, double-click the app target in the Groups and Files list to open the Info window for the target. Then display the Properties pane of the window and replace “NSApplication” in the Principal Class field with the name of your custom class. The
NSApplicationMain function sends
shared() to the principal class to obtain the global app instance (
NSApp)—which in this case will be an instance of your custom subclass of
Methods to Override
Generally, you subclass
NSApplication to provide your own special responses to messages that are routinely sent to the global app object (
NSApplication does not have primitive methods in the sense of methods that you must override in your subclass. Here are four methods that are possible candidates for overriding:
run()if you want the app to manage the main event loop differently than it does by default. (This a critical and complex task, however, that you should only attempt with good reason.)
sendEvent(_:)if you want to change how events are dispatched or perform some special event processing.
requestUserAttention(_:)if you want to modify how your app attracts the attention of the user (for example, offering an alternative to the bouncing app icon in the Dock).
target(forAction:)to substitute another object for the target of an action message.
The global app object uses
@autorelease blocks in its
run() method; if you override this method, you’ll need to create your own
Do not override
shared(). The default implementation, which is essential to app behavior, is too complex to duplicate on your own.
Alternatives to Subclassing
NSApplication defines numerous Delegation methods that offer opportunities for modifying specific aspects of app behavior. Instead of making a custom subclass of
NSApplication, your app delegate may be able to implement one or more of these methods to accomplish your design goals. In general, a better design than subclassing
NSApplication is to put the code that expresses your app’s special behavior into one or more custom objects called controllers. Methods defined in your controllers can be invoked from a small dispatcher object without being closely tied to the global app object.