Guides and Sample Code Developer
Document Generated: 2016-06-07 18:54:11 -0700
macOS Release Notes Copyright © 2016 Apple Inc. All Rights Reserved.

macOS 10.12 Release Notes
Cocoa Application Framework

The Cocoa Application Framework (also referred to as the Application Kit, or AppKit) is one of the core Cocoa frameworks. It provides functionality and associated APIs for applications, including objects for graphical user interfaces (GUIs), event-handling mechanisms, application services, and drawing and image composition facilities.

Some of the major topics covered in this document:

These are the AppKit release notes for macOS v10.12.

Release notes for AppKit from 10.11 and earlier releases can be found here.

Note that even though some APIs and descriptions refer to the APIs in Objective-C, and some others in Swift, unless otherwise specified all AppKit APIs are available in both Objective-C and Swift.

Marking updated APIs in headers

New APIs in headers are marked with decorations that include references to "10_12":
 NS_AVAILABLE_MAC(10_12), NS_AVAILABLE(10_12, <iOS Release>), NS_CLASS_AVAILABLE(10_12, <iOS Release>), NS_ENUM_AVAILABLE(10_12)
Deprecated APIs are marked with:

NS_DEPRECATED_MAC(<Release when introduced>, 10_12) or NS_DEPRECATED_MAC(<Release when introduced>, 10_12, "Suggested alternative")

Runtime Version Check

There are several ways to check for new features provided by the Cocoa frameworks at runtime. One is to look for a given new class or method dynamically, and not use it if not there. Another is to use the global variable NSAppKitVersionNumber (or, in Foundation, NSFoundationVersionNumber):
double NSAppKitVersionNumber;
. . .
#define NSAppKitVersionNumber10_7 1138
#define NSAppKitVersionNumber10_8 1187
#define NSAppKitVersionNumber10_9 1265
#define NSAppKitVersionNumber10_10 1343
#define NSAppKitVersionNumber10_10_2 1344
#define NSAppKitVersionNumber10_10_3 1347
#define NSAppKitVersionNumber10_10_4 1348
#define NSAppKitVersionNumber10_10_5 1348
#define NSAppKitVersionNumber10_10_Max 1349
#define NSAppKitVersionNumber10_11 1404
One typical use of this is to floor() the value, and check against the values provided in NSApplication.h. For instance:
if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_9) {
/* On a 10.9.x or earlier system */
} else if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_10) {
/* On a 10.10 system */
} else if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_10_x) {
/* on a 10.10.x system */
. . .
} else if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_11) {
/* on a 10.11 or 10.11.x system */
} else {
/* on a 10.12 or later system */
Note that unlike most AppKit software updates, 10_10 software updates incremented the AppKit major version, which accounts for the specific advice for 10_10.x. Other special cases or situations for version checking are discussed in the release notes as appropriate. For instance some individual headers may also declare the versions numbers for NSAppKitVersionNumber where some bug fix or functionality is available in a given update, for example:
#define NSAppKitVersionWithSuchAndSuchBadBugFix 1138.42

Backward Compatibility

One backward compatibility mechanism that is occasionally used in the frameworks is to check for the version of the system an application was built against, and if an older system, modify the behavior to be more compatible. This is done in cases where bad incompatibility problems are predicted or discovered; and most of these are listed below in these notes.

Typically we detect where an application was built by looking at the version of the System, Cocoa, AppKit, or Foundation frameworks the application was linked against. Thus, as a result of relinking your application against the latest SDK, you might notice different behaviors, some of which might cause incompatibilities. In these cases because the application is being rebuilt, we expect you to address these issues at the same time as well. For this reason, if you are doing a small incremental update of your application to address a few bugs, it's usually best to continue building on the same build environment and libraries used originally.

In some cases, we provide defaults (preferences) settings which can be used to get the old or new behavior, independent of what system an application was built against. Often these preferences are provided for debugging purposes only; in some cases the preferences can be used to globally modify the behavior of an application by registering the values (do it somewhere very early, with -[NSUserDefaults registerDefaults:]).

Overall API Updates

This release brings many API refinements, taking advantage of new API features in Objective-C and enabling APIs to come across more naturally in Swift.

Some of the key API update areas include:
- Adoption of Swift 3 API design guidelines, which has a large impact on the APIs as they appear in Swift.
- Adoption of Foundation Value Types, where appropriate in APIs. For instance NSData and NSURL in API now appear as Data and URL in Swift.  (Note that prefix dropping is a Foundation-only change and does not apply to other frameworks.)
- Updated names of enumerations to improve consistency and exposure in Swift.

Note that there are still a number of API changes we intend to do in 10.12, including increased adoption of class properties and string enumerations features.  You may see this in upcoming seeds of 10.12.

NSCollectionView: Collapsible Sections

Finder’s icon view offers users the ability to collapse any section (each grouping by kind in “Arrange by: Kind” mode, for example) into a single horizontally scrollable row, via a “Show Less” button in the section’s header. A section will sometimes start out in this collapsed state, with the button (now titled “Show All”) toggling the section back into a normal flow layout. You can now easily offer the same capability to users of your NSCollectionViews.

To enable this feature:

1. Make your header view conform to the new NSCollectionViewSectionHeaderView protocol. This protocol provides an optional "sectionCollapseButton” property that we’ll use the help the CollectionView find the button.

2. Add an NSButton as a subview or descendant of your section header view. (If you’re using .xib files, you can do this in the interface editor.)

3. Set the button’s image or title to something general that indicates a toggle action — or, if desired, to indicate an initially uncollapsed state. (e.g. You’re likely to want it to read “Show Less”, or similar.)

4. Set up Auto Layout constraints to position your button as desired within the header view.

5. Wire the header view’s “sectionCollapseButton” outlet to your button.

6. Wire your button’s action to send -toggleSectionCollapse: to the First Responder. (Alternatively, you can use another action of your own, and have its implementation use either -toggleSectionCollapse: or the programmatic collapse/expand API described below to change the section’s state as desired.)

When the user clicks the button, -toggleSectionCollapse: should get routed to the NSCollectionView, which identifies the section based on the enclosing header view instance, and toggles the section’s collapsed state.

As in Finder’s icon view, the button is automatically shown when applicable, and hidden when not. If you want to change the title of the button to reflect the current collapsed/uncollapsed state, you can do so by overriding the -toggleSectionCollapse: action method on NSCollectionView to update the button’s title, after calling up to super. For example:
// Override -toggleSectionCollapse: to update the button's title.
- (void)toggleSectionCollapse:(id)sender { // "sender" is the "Show Less" / "Show All" button.
    // Let NSCollectionView collapse or expand the corresponding section.
[super toggleSectionCollapse:sender];
    // Update the button's label to show the action it will now perform.
if ([sender isKindOfClass:[NSButton class]]) {
// We must have a Flow layout, to be able to collapse and expand sections.
NSCollectionViewFlowLayout *layout = (NSCollectionViewFlowLayout *)[self collectionViewLayout];
if ([layout isKindOfClass:[NSCollectionViewFlowLayout class]]) {
            // Find the containing header view, and from it the corresponding sectionIndex.  (The `sender` button is required to reside in a section Header view.)
NSSet<NSIndexPath *> *headerIndexPaths = [self indexPathsForVisibleSupplementaryElementsOfKind:NSCollectionElementKindSectionHeader];
NSUInteger sectionIndex = NSNotFound;
for (NSIndexPath *headerIndexPath in headerIndexPaths) {
NSView *headerView = [self supplementaryViewForElementKind:NSCollectionElementKindSectionHeader atIndexPath:headerIndexPath];
if (headerView && [(NSView *)sender isDescendantOf:headerView]) {
sectionIndex = [headerIndexPath section];
            if (sectionIndex != NSNotFound) {
NSString *newLabel;
if ([layout sectionAtIndexIsCollapsed:sectionIndex]) {
newLabel = [NSString stringWithFormat:@"Show All (%lu)", (unsigned long)[self numberOfItemsInSection:sectionIndex]];
} else {
newLabel = @"Show Less";
[(NSButton *)sender setTitle:newLabel];
This example method uses API that enables you to programmatically query and change the collapsed/expanded state of any section:
@interface NSCollectionViewFlowLayout
/* Returns YES if the specified section is currently collapsed; NO if not, or if there is no such section. Defaults to NO.
- (BOOL)sectionAtIndexIsCollapsed:(NSUInteger)sectionIndex NS_AVAILABLE_MAC(10_12);
/* Collapses the specified section to a single row, if it is not already collapsed.
- (void)collapseSectionAtIndex:(NSUInteger)sectionIndex NS_AVAILABLE_MAC(10_12);
/* Un-collapses the specified section, if it is currently collapsed.
- (void)expandSectionAtIndex:(NSUInteger)sectionIndex NS_AVAILABLE_MAC(10_12);

NSCollectionView: Floating Headers

Header and Footer views in a Flow layout can now be “floated”, using the same API provided by iOS’ UICollectionView.

Set these properties to YES to get headers that pin to the top of the visible area and footers that pin to the bottom while scrolling. These properties are archived with the layout's other persistent properties. Enabling this feature may affect the parenting of header and footer views.

@interface NSCollectionViewFlowLayout
@property BOOL sectionHeadersPinToVisibleBounds NS_AVAILABLE_MAC(10_12);
@property BOOL sectionFootersPinToVisibleBounds NS_AVAILABLE_MAC(10_12);
When sectionHeadersPinToVisibleBounds is set to YES, the header view (if any) for the topmost visible section will stay pinned to the top of the scroll area in preference to being scrolled out of view. As the user scrolls down, the header stays pinned there until the next section’s header (or the top of the next section, if the next section has no header) pushes it out of the way.

The sectionFootersPinToVisibleBounds property behaves similarly, with pinning to the bottom of the scroll area provided instead.

NSCollectionView: Scrollable Background Views

An NSCollectionView’s backgroundView can now be set to scroll together with the CollectionView’s content, instead of floating stationary behind the content. When backgroundViewScrollsWithContent is YES, the CollectionView's backgroundView (if any) will match the CollectionView's frame and scroll with the CollectionView's items and other content. When NO (the default, compatible with the behavior on OS X 10.11), the backgroundView is made to fill the CollectionView's visible area, and remains stationary when the CollectionView's content is scrolled. This property is archived with the CollectionView's other persistent properties.

@interface NSCollectionView
@property BOOL backgroundViewScrollsWithContent NS_AVAILABLE_MAC(10_12);
Setting this property necessarily changes the way the backgroundView is parented. To float the backgroundView behind scrolling content, we make it a sibling of the CollectionView’s ClipView (as on 10.11). To have it scroll with the CollectionView’s content, we instead make the backgroundView a subview of the CollectionView.

The backgroundView property is meant to interoperate with backgroundColors (and now does so better, thanks to a fix in 10.12). If a CollectionView has both a backgroundView and backgroundColors, backgroundColors[0] will show through any areas not opaquely covered by the backgroundView. (backgroundColors beyond the first element are a legacy feature of NSCollectionView from OS X < 10.11. When using 10.11’s “new” NSCollectionView, only the first color is used.)

The backgroundView’s frame is set to match the CollectionView’s, and updated automatically to maintain that equality.

NSCollectionView: File Promise Drag Fix

On OS X 10.11, a dataSource-based NSCollectionView acting as the dragging source for a file promise drag would erroneously attempt to invoke the old -collectionView:namesOfPromisedFilesDroppedAtDestination:forDraggedItemsAtIndexes: delegate API method, instead of first checking for the newer -collectionView:namesOfPromisedFilesDroppedAtDestination:forDraggedItemsAtIndexPaths: API (and would raise an exception if the old-form delegate method wasn’t found). This has been fixed, so that NSCollectionView will first look for and attempt to invoke the new method. Failing presence of the new method, NSCollectionView will fall back to the old method, but only if it is a single-section CollectionView.

NSCollectionView: Delegate Message Send Fix

On 10.12, an NSCollectionView’s delegate now receives -collectionView:didEndDisplayingItem:forRepresentedObjectAtIndexPath: (and the corresponding items are placed in the CollectionView’s reuse queue) for all currently instantiated items when the CollectionView is removed from its window, and not just when the items are scrolled out of view or removed. This makes -collectionView:didEndDisplayingItem:forRepresentedObjectAtIndexPath: a more reliable cleanup opportunity for resources that may be associated with items. The same is true for -collectionView:didEndDisplayingSupplementaryView:forElementOfKind:atIndexPath: (which due to a bug was not sent at all on OS X 10.11).

On 10.12, -collectionView:willDisplaySupplementaryView:forElementKind:atIndexPath: is now sent for a supplementary or decoration view that is about to be displayed. Due to a bug, this delegate message was not sent on OS X 10.11.


NSCollectionViewGridLayout now implements -initWithCoder: and -encodeWithCoder: to persist and restore its properties as it should. It did not do so on OS X 10.11.


NSToolbar's contextual menu will no longer show the "Hide Toolbar" item in applications linked on or after 10.12. Please be sure to include a menu item in your application's menu bar to toggle this behavior.

NSSlider isVertical

NSSlider and NSSliderCell's `vertical` property is now readwrite and has changed its type from NSInteger to BOOL. In previous releases, NSSliderCell would try to automatically determine its orientation based on the aspect ratio of a received cell frame. This also led to -1 being returned from `isVertical` if it could not make a determination (e.g. the cell frame had a zero size), and could lead to the slider changing orientation when it was resized.
With 10.12, the vertical property is set at initialization time based on the aspect ratio of the frame parameter, and defaults to horizontal in ambiguous (equal width/height) cases; however it is recommended to explicitly set the vertical property or use the convenience constructors. To dynamically change the orientation of the slider, explicitly set the `vertical` property.

NSSplitView Delegate

For apps linked against the 10.12 SDK, NSSplitView's delegate property has zeroing `weak` memory semantics, compared to the previous `assign` memory semantics. However, if the object being set as the delegate doesn't support weak references, it will fallback to having assign semantics.
When linked against an older SDK, the delegate will continue to have `assign` semantics even when run on 10.12 or later.
It is important for apps that deploy to older OS X versions to still code against the `assign` semantics, and clear the delegate property when the delegate object is deallocated.

NSAlert Delegate

For apps linked against the 10.12 SDK, NSAlert's delegate property has zeroing `weak` memory semantics, compared to the previous `retain` memory semantics. However, if the object being set as the delegate doesn't support weak references, it will fallback to having assign semantics on 10.12.
When linked against an older SDK, the delegate will continue to have `retain` semantics even when run on 10.12 or later.
It is important for apps that deploy to older OS X versions to still consider the `retain` behavior and protect against retain cycles.

NSAlert Used Outside of Runloop

With 10.11 showing a modal NSAlert (or any other UI) outside of the main runloop will cause it to not disappear on modal session end. With 10.12, these alerts will be visually dismissed for apps linked against the 10.10 SDK or earlier. For newer apps, alerts should only be shown within the main run loop; or in cases where that is not possible, apps should make sure to flush the CATransaction after the modal run of the alert finishes (i.e. +[CATransaction flush]).


Prior to OS 10.12, -[NSCursor initWithImage:foregroundColorHint:backgroundColorHint:hotSpot:] would act as a designated initializer. The color hint parameters were unused and are now deprecated. For apps linked on or after OS 10.12, the color hint initializer calls into the new designated initializer, "-[NSCursor initWithImage:hotSpot:]". Apps which depend on which initializer is called should move to the new designated initializer.

NSCursor now better handles NSImage objects that contain vector representations and/or bitmap representations larger than @2x. It will now use the best available representation when the cursor is scaled via Accessibility preferences.

Layout Pass

In 10.12, the deferred view layout pass has been cleaned up, optimized and extended. This has resulted in several changes that developers should be mindful of when implementing view layout.

The deferred view layout pass represented by [NSView setNeedsLayout:] and [NSView layout] is now independent of autolayout and constraints. As a result, you can now implement custom layout mechanisms by overriding [NSView layout] without implicitly activating autolayout on the window. For example, if a view has child CALayers, it can now cleanly lay out those child layers in a [NSView layout] override and simply call [self setNeedsLayout:YES] whenever the child layout geometry needs to be updated in a deferred layout pass.

Previously, there were times where CoreAnimation would trigger [NSView layout] calls on parts of the view hierarchy out of band with the rest of the layout pass, resulting in inconsistent layout pass behavior or sometimes excessive layout calls on parts of the view hierarchy. The view layout pass is now driven entirely by AppKit. There could be cases where custom views were laying out child views or layers in a [view layout] override and were not setting view.needsLayout=YES appropriately, but the problem was masked by CoreAnimation. The solution in these cases is to ensure that view.needsLayout=YES is set whenever necessary. Note that layout for a view is now automatically invalidated when the view’s frame size changes, so view.needsLayout=YES should only be necessary on relevant state changes.

When overriding [NSView layout], AppKit no longer requires calling [super layout]. In particular, the view.needsLayout bit is now cleared automatically outside of the [view layout] call. This allows you to completely override [view layout] and block all of the default layout behavior if so desired. Also note that the bit is cleared before [view layout] is called, which means that if you dirty layout during your [view layout] override (either via calling [view setNeedsLayout:YES] directly or by modifying constraints), it will schedule a second layout pass.

Coordinated with a generic layout pass, AppKit now attempts to be smarter about when to actually engage an autolayout engine on an NSWindow. Specifically, the presence of an override to [NSView updateConstraints] now indicates to AppKit that the view in question, by default, uses constraints, and as such will activate autolayout in any NSWindow into which it is placed. If, however, you are writing a custom view type that supports but does not require constraints, then the correct solution, as before, is to override the class-level [NSView requiresConstraintBasedLayout] method and return NO.

As part of the layout pass optimization, AppKit is now more strict about certain requirements and limitations of the API. In particular:

- Be mindful of how layout is applied in a deferred manner, such that a view cannot rely on the frames of any subviews being current when its frame changes or during the view’s layout call (the ordering is not guaranteed). If you implement custom layout behaviors on top of deferred constraint-based layout and require the frames being current, the correct method is to call [self layoutSubtreeIfNeeded], which will perform the layout pass synchronously for just that subtree. Also note that using [self layoutSubtreeIfNeeded] is in general good practice if you are relying on frames of descendant views provided by other frameworks or libraries, since it can be difficult to determine whether any of those components use deferred layout or not, and the answer might change from release to release.

- AppKit is now more efficient about only calling -layout on views when actually necessary, which can reveal holes where code previously did not properly invalidate layout when necessary (the above CoreAnimation case being one of those instances). If you find -layout method not being called when expected on your view, make sure that the view is actually marked as needsLayout=YES.

- There are certain API calls that are specific to autoresizing masks or constraint-based layouts, and using one or the other, particularly in view hierarchies where both methods are used, can lead to unexpected results. Specifically, the resizeSubviewsWithOldSize/resizeWithOldSuperviewSize pair of API calls are specifically tied to autoresizing masks and whether a view has autoresizesSubviews set, and as a consequence those API calls can—and most likely will—be called before any constraint-based view layout is performed. The best layout-method-agnostic method of watching for size changes on a custom view class continues to be overriding the [NSView setFrameSize] call, and the best method for laying out children is to override [NSView layout], since it no longer automatically implies autolayout activation.

- The constraint solver works best when a set of layout constraints are activated once and left alone to re-evaluate as necessary during resize. However, if you must modify constraints as your view resizes, the best method continues to be overriding [NSView updateConstraints] and then setting self.needsUpdateConstraints=YES from within an [NSView setFrameSize] override. This method reduces the chance of a layout loop, makes layout dependencies easier to debug, and allow AppKit to better optimize the performance of the layout changes.

Improved debugging support for layout

AppKit now provides some additional support for debugging layout feedback loops. If you encounter layout passes that do not terminate naturally, you can run your application with the following argument: -NSViewLayoutFeedbackLoopDebuggingThreshold 100. The framework will then track dirty layout and attempt to identify cycles, logging information that may be useful in isolating the problem.

To assist debugging redundant view layout, there are now two user defaults. NSViewLayoutStrictMode, when enabled, will log the pointer of the view receiving redundant layout. This behavior can be modified to throw an exception by setting the NSViewLayoutStrictModeThrowsException user default to YES. NSViewLayoutStrictModeThrowsException has no effect when NSViewLayoutStrictMode is not set to YES.

Item Based Dragging File Promises

The Drag & Drop API has been modernized with two new classes: NSFilePromiseProvider and NSFilePromiseReceiver. These new objects:
    •    Support drag flocking
    •    UTI based
    •    Pasteboard Writer/Reader compliant
    •    File coordinated when possible
Also, NSFilePromiseProvider is compatible with drag destinations using the non-item based drag file promise API. Likewise, NSFilePromiseProvider is compatible with dragging sources using the non-item based drag file promise API.

Dragging File Promise Source

Use the NSFilePromiseProvider class when creating file promises. Instantiate one NSFilePromiseProvider for each file promised. Before writing any NSFilePromiseProvider to the pasteboard, it must contain a file type being promised and an NSFilePromiseProviderDelegate. The file type must be a UTI that ultimately conforms to kUTTypeData or kUTTypeDirectory. The NSFilePromiseProviderDelegate will do the heavy lifting of writing the promised file to the destination directory. Optionally, you may attach a userInfo object of your choosing to the NSFilePromiseProvider. This is often useful to determine which promise is being referenced when promising multiple files and using the same NSFilePromiseProviderDelegate instance.

There are only three NSFilePromiseProviderDelegate methods you need to implement:
- (NSString *)filePromiseProvider:(NSFilePromiseProvider*)filePromiseProvider fileNameForDestination:(NSURL *)destinationURL;
Discussion: This method is called when the drag destination “calls in” the file promise. At this point you should determine and return the final filename, which should be the base filename, not a full path. You may inspect the destination directory to resolve any file name conflicts before settling on a final filename. Note: The drag process is halted while waiting for this method to return. Taking too long in this method may result in the drag getting cancelled. Do not start writing the file yet.

- (void)filePromiseProvider:(NSFilePromiseProvider*)filePromiseProvider writePromiseToURL:(NSURL *)url
completionHandler:(void (^)(NSError *errorOrNil))completionHandler;
Discussion: Write the contents of this promise item to the provided URL and call completionHandler when done. While technically an optional method, you must implement this method. The optional attribute allows for future expandability. It is important to call the completion handler as the file writing is wrapped with NSFileCoordinator. Likewise, be sure write your file to the supplied url parameter. This method is called after the drag completes. Note: This request shall occur on the NSOperationQueue supplied by -promiseOperationQueue.
- (NSOperationQueue *)promiseOperationQueueForFilePromiseProvider:(NSFilePromiseProvider*)filePromiseProvider;
Discussion: Return the operation queue that the write request should be issued from. If this method is not implemented, the mainOperationQueue is used. While optional, it is strongly recommended that you provide an operation queue other than the main operation queue to avoid blocking your main thread.

Dragging File Promise Destination

Use the NSFilePromiseReceiver object to receive file promises. Since NSFilePromiseReceiver implements the NSPasteboardReader protocol, you get all the file promises on the drag pasteboard like so:
    NSArray<NSFilePromiseReceiver*> filePromises = [pasteboard readObjectsForClasses:@[[NSFilePromiseReceiver class]] options:nil];
Likewise you can enumerate the draggingItems by
   [draggingInfo enumerateDraggingItemsWithOptions:0 forView:view classes:@[[NSFilePromiseReceiver class]] searchOptions:@{}
usingBlock:^(NSDraggingItem *draggingItem, NSInteger idx, BOOL *stop) {
NSFilePromiseReceiver *filePromiseReceiver = dragItem.item
Compatibility note: A non-item based drag source (e.g. don’t use NSFilePromiseProvider) may promise multiple files on the same pasteboard item. To be compatible with these drag sources many NSFilePromiseReceiver methods return an array of values. Muti-file item based promises result in one NSFilePromiseReceiver per promised file.
+ (NSArray<NSString *> *)readableDraggedTypes;
Discussion: A view must register what types it accepts via -registerForDraggedTypes:. Use this class method to get the file promise drag types that NSFilePromiseReceiver can accept, in order to register a view to accept promised files. NSFilePromiseReceiver can accept file promises from both the item based NSFilePromiseProvider and the non-item based API. If you don’t register all these drag types you may fail to be notified about some file promise drags. Registration is simply: [view registerForDraggedTypes:[NSFilePromiseReceiver readableDraggedTypes]];
@property(copy, readonly) NSArray<NSString*> *fileTypes;
Discussion: Returns an array of UTIs for the filetypes promised. NSFilePromiseProvider promises 1 filetype per item. The count of fileTypes should tell you the number of promised files in this item, however, that is not guaranteed. Historically, some legacy file promisers only list each unique fileType once and write one or more files per type.
- (void)receivePromisedFilesAtDestination:(NSURL *)destinationDir options:(NSDictionary *)options
operationQueue:(NSOperationQueue *)operationQueue reader:(void(^)(NSURL *fileURL, NSError * __nullable errorOrNil))reader;
Discussion: This effectively calls in the promises. Therefore, only call once you are accepting the file promise. All file promisesReceiver's in a drag must specify the same destination location. The options dictionary is ignored for now. The reader block is called on the supplied operationQueue when the promised file is ready to be read. It is highly recommended that you specify an optation queue other than the main operation queue to avoid blocking the main thread waiting for the file promise to be written by the source (as this may be a long process). When the source is an NSFilePromiseProvider, the readerBlock call is wrapped in an NSFileCoordination read. Otherwise, a heuristic is used to determine when the promised file is ready to be read. Note: Writing of the promised file may fail. When that occurs, the readerBlock is still called with a non-nil error. There may be nothing at the fileURL, or it may be a partial / corrupt file.
@property(copy, readonly) NSArray<NSString*> *fileNames;
Discussion: Returns an array of the file names of the promised files that are being written to the destination location. This property returns an empty array until the file promise is called in via receivePromisedFilesAtDestination.


Built-in NSControl subclasses now automatically mirror some directional properties (e.g. NSButton’s imagePosition) when unarchived from a Base-localized Interface Builder archive into a right-to-left user interface. This behavior is suppressed if the control is configured with “Mirror” set to “Never”.

The cases of the NSControlSize enumeration have been renamed to have a common prefix, per modern naming conventions. The existing names are now deprecated.

The -[NSControl sendAction:to:] method incorrectly declared its `theAction` parameter as non-nullable. It is now correctly marked as nullable.


The previously-unused gradientType property, and corresponding NSGradientType enumeration, are now deprecated.


NSButton now has several new convenience constructors for creating system standard push buttons, checkboxes, and radio buttons.

NSButton’s keyEquivalentModifierMask property is now declared with type NSEventModifierMask instead of NSUInteger.


NSTextField now has several new convenience constructors for creating non-wrapping labels, wrapping labels, attributed labels, and editable text fields.

The -control:isValidObject: delegate method incorrectly declared the `object` parameters as nonnull. It is now correctly marked as nullable.


NSSegmentedControl has new convenience constructors for creating a segmented control given an array of labels or an array of images.


NSSlider has new convenience constructors for creating horizontal linear sliders.


NSImageView has a new convenience constructor for creating a non-editable image view with a given NSImage.

New Layout Container: NSGridView

NSGridView is an auto layout container for arranging content views into a grid. At a high level it's similar to NSStackView, except it allows for alignment across both rows and columns. Like a spreadsheet, rows and columns can all be varying sizes, or dynamically hidden & shown. Individual cells may be merged to achieve a layout that crosses the basic grid boundaries. See NSGridView.h for more the API and more information.


NSLayoutConstraint now exposes properties for a firstAnchor and nullable secondAnchor. This is part of a longer-term move towards leveraging layout anchors more heavily in the API. Use of these is recommended over the existing item/attribute pairs, since some anchors cannot be represented that way. For this reason, NSLayoutConstraint's firstItem property is now nullable, and developers may begin to encounter valid constraints with nil items or NSLayoutAttributeNotAnAttribute.


In NSAccessibilityConstants.h, added the role constant “NSAccessibilityMenuBarItemRole” for menubar status items.

In NSAccessibilityProtocols.h, the NSAccessibilityLayoutArea protocol now declares accessibilityFocusedUIElement as a read-only property rather than a method, so that it matches the NSAccessibility protocol. This allows Swift classes to implement the NSAccessibilityLayoutArea protocol by overriding the property.

In NSAccessibilityConstants.h, added a new constant “NSAccessibilityRequiredAttribute” which indicates that a form field is required to have content for successful submission of the form. In NSAccessibilityProtocols.h, defined the corresponding protocol method for setting and getting the value of this attribute on an accessible object.


NSMenuItem’s keyEquivalentModifierMask property is now declared with type NSEventModifierMask instead of NSUInteger.

NSMenu and NSMenuItem now conform to the NSUserInterfaceItemIdentification protocol.

NSMenu and NSMenuItem now conform to the NSAccessibility and NSAccessibilityElement protocols. These classes now support the accessibility identifier and description that can be set in Interface Builder. You can also change the accessibility description in code with the -setAccessibilityLabel property setter.

NSMenu's delegate property is now declared "weak". The NSMenu implementation has actually stored a weak reference to the delegate (for zeroing-weak-compatible objects) since OS X v10.9, so this change is not a change in behavior but simply documents the current implementation.

The behavior of -[NSMenu performKeyEquivalent] has changed when the specified event corresponds to a disabled menu item. Previously, this method could return either NO (no match found) or YES (match found) depending on whether the NSEvent contained a Carbon EventRef. This behavior has now been made consistent for applications linked on macOS 10.12 and later; regardless of whether the NSEvent contains an EventRef, -performKeyEquivalent will return YES if the event corresponds to a menu item, even if the menu item is disabled. If the item is disabled, its action will not be performed. Note: in the next seed, this change will be reverted due to its impact on binary compatibility.

NSTableView / NSOutlineView

NSTableView properly supports Right to Left Layout for applications that link on 10.12 and higher. Previously, the userInterfaceLayoutDirection was hardcoded to be NSUserInterfaceLayoutDirectionLeftToRight. NSTableView and NSOutlineView will now automatically flip the table column order for applications are right to left. This is only affects the visual representation of the table columns; the actual logical tableColumn array order is still maintained.

NSTableView (and NSOutlineView) now has a proper weak delegate and dataSource implementation. This means a developer is no longer required to clear them out to nil when the delegate (and/or dataSource) object is freed. This change applies to all applications on 10.12. Applications that target older releases should still reset the delegate to nil; doing so is harmless for 10.12 and higher. Note that the _delegate and _dataSource ivars in NSTableView have always been private, and should not be directly accessed. In 10.12, they are now opaque objects, and may not represent the real delegate or dataSource. Instead of directly using the ivars, one should use the property accessors.

NSOutlineView has a new property named stronglyReferencesItems to allow it to automatically retain the items returned to it when set to YES. The default value is YES for applications linked on 10.12 and higher, and NO otherwise. In general, this value should always be YES, but can be set back to NO for cases where the items would cause a retain cycle. This could happen if the item either directly or indirectly retained the outline view, which would cause it to never get released.

NSOutlineView will now reload the cell views associated with ‘item’ when [outlineView reloadItem:] is called. The method simply calls [outlineView reloadDataForRowIndexes:columnIndexes:] passing the particular row that is to be reloaded, and all the columns. For compatibility, this will only work for applications that link against the 10.12 SDK.

NSTableView will now reload "full width" cell views (meaning the column index for them is -1) when [tableView reloadDataForRowIndexes:columnIndexes:] is called, and the column index contains -1. For compatibility, this will only work for applications that link against the 10.12 SDK.


The class now has a new material for selection: NSVisualEffectMaterialSelection. In addition, a new property called emphasized can be used to indicate that the selection should draw in "first responder" status, or not.


NSTitlebarAccessoryViewController supports NSLayoutAttributeLeading and NSLayoutAttributeTrailing to specify an abstract position that automatically flips depending on the localized language. These only work for applications that link on 10.12 and later. For applications that do not link on 10.12, NSLayoutAttributeLeft will automatically flip to the Right when in a Right To Left language and when run on 10.12.

NSWindow's backgroundColor would be ignored if a custom appearance was set on the window, and the window's contentView had wantsLayer=YES. This has been fixed for all applications.

Replacing the contentViewController on an visible NSWindow would leave the firstResponder set to the window; this has now been fixed to automatically determine the correct first responder when the contentViewController is changed. Applications targeting prior OS releases should explicitly assign the firstResponder in the new contentViewController's viewWillAppear.

NSWindow's +windowWithContentViewController: binds the resulting window's title to that of the set contentViewController. On 10.12 and later, NSWindows loaded from storyboards will have the same behavior.

NSWindow Automatic Window Tabbing

Automatic Window Tabbing allows any application to easily (and automatically) adopt tabs. This feature stacks multiple windows together and presents a tab bar in the window title bar area to make it appear to the user as though there is one single window. In reality, only the selected tab's window is shown, and all the other windows are hidden directly using CoreGraphics. An application only has to order a window in, and it will automatically be tabbed with similar windows based on heuristics the user's preference for tabbing. Ordering a window out removes the tab. Windows that are not visible are ordered out with respect to CoreGraphics, but are still considered visible with respect to AppKit / NSWindow.

There is a new user System Preference under the Dock section to control tabbing. The behavior of this preference is described in General Flow below.

The NSWindow header has two new enumerations (NSWindowUserTabbingPreference, NSWindowTabbingMode) and several new properties. Please examine the header for some detailed comments on what the new methods are for.

API Adoption

    •    What should an application which works well with out-of-the-box window tabbing do? - In general, nothing has to be done. A non-NSDocument based application may wish to support the "+" button by implementing newWindowForTab: somewhere in the responder chain.
    •    What should an application which already has support for tabbing do? - The application should explicitly opt-out of automatic window tabbing by calling [NSWindow setAllowsAutomaticWindowTabbing:NO]. It should respect the userTabbingPreference and create tabs based on the General Flow described below.
    •    What should an application do to customize the standard tabbing behavior? - See the detailed Behavior section below for how the properties interact with each other.

General Flow

The behavior depends on the new system preference under the Dock section to allow tabbing: Always / In Full Screen Only [Default] / Manually. Holding down option, in general, will invert the standard behavior. For each option:

When In Full Screen Only [Default]:

* When in Full Screen all windows opened will prefer to tab, including menu items (Cmd-N, Open Recents, etc), the open panel, and opening documents from Finder.
* When in Full Screen Holding down option will prefer to window [in a new space] instead of a tab
* When on the Desktop things work exactly as they always have, with the additional ability to create tabs manually. See Manually.

When Always:

* When on the Desktop or in Full Screen opening similar windows should prefer to always tab, including menu items (Cmd-N, Open Recents, etc), the open panel, and opening documents from Finder.
* Holding down the option button will prefer to create a window instead of a tab.

When Manually:

* When on the Desktop or in Full Screen opening windows will prefer to just create a normal window.
* Holding down the option button will prefer to create a tab instead of a window.


The userTabbingPreference is a representation of the system preference for tabbing. Applications that already explicitly adopt tabbing, including ones that do not use automatic window tabbing, should read the value of the userTabbingPreference before showing a window to determine if a regular show of a window should prefer to tab with other windows, or be shown in a new window.

[NSWindow allowsAutomaticWindowTabbing] is a way for an application to opt-out of automatic window tabbing. An application that opts out will not get the standard menu items that perform tabbing. The default value for allowsAutomaticWindowTabbing will be YES for all applications except for some that are specifically black-listed out. Those apps can explicitly adopt automatic window tabbing by setting the value of allowsAutomaticWindowTabbing to YES early in the application bring up (in applicationWillFinishLaunching).

A window’s tabbingMode always defaults to NSWindowTabbingModeAutomatic. When the tabbingMode is set to NSWindowTabbingModeAutomatic, and [NSWindow allowsAutomaticWindowTabbing] is YES, the system will automatically tab together similar windows based on tabbingIdentifier. Automatic window tabbing will attempt to tab together windows based on the userTabbingPreference, and how the window was created (based on the logic in “General Flow of Automatic Window Tabs”). When the tabbingMode is set to NSWindowTabbingModeAutomatic, and [NSWindow allowsAutomaticWindowTabbing] is NO, no automatic window tabbing will happen.

A window’s tabbingMode can explicitly be set to NSWindowTabbingModePreferred to allow the window to tab together with other similar windows based on the tabbingIdentifier. This can be set anytime an application wants a window to become in a tab. For instance, it can be set to NSWindowTabbingModePreferred for a window created by a Cmd-T shortcut to always create a window in a tab, regardless of any other system settings, and regardless of the userTabbingPreference. It is up to an application to properly respect the userTabbingPreference and set NSWindowTabbingModePreferred only at appropriate times.

A window’s tabbingMode can explicitly be set to NSWindowTabbingModeDisallowed to explicitly disallow window tabbing. It is up to an application to properly respect the userTabbingPreference and set NSWindowTabbingModePreferred only at appropriate times based on the logic in “General Flow of Automatic Window Tabs”.

A window’s tabbingMode is only checked when a window is about to be shown, and the tabbingMode should be updated before the window is ordered in.

New Button

The plus button will be shown if newWindowForTab: is implemented in the responder chain. NSDocumentController informally implements newWindowForTab:, but only returns YES from respondsToSelector: for this selector if the self.documentClassNames.count > 0. In other words, it only responds to it if NSDocument has at least one registered document class name.

NSWindow Actions

An application can utilize the standard window tabbing actions to select tabs, merge them into one window, etc: -selectNextTab:, -selectPreviousTab:, -moveTabToNewWindow:, -mergeAllWindows:, -toggleTabBar:.

By default, applications with automatic tabbing will get standard tab menu items added under the Window menu that are hooked up to these actions. However, an app may wish to add contextual menu options that perform the actions. Or, an application which opts-out of automatic tabbing (by setting NSApp.allowsAutomaticWindowTabbing=NO) may still wish to participate in tabs.

To validate the above actions, NSWindow will perform the validation inside its implementation of - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item;, but only if the selector matches one of the above items.


Prior to macOS 10.12, NSAnimationEaseOut was reversed. It would perform an "ease in" animation beginning at the final value and ending at the initial value. For apps linked on or after macOS 10.12, NSAnimationEaseOut now describes a curve beginning at the initial value and ending at the final value, that slows down towards the end.


NSImage now supports multiple representations to support different user interface layout directions.

This can be configured in Xcode for images loaded through asset catalogs. If you are building an image programmatically, note than NSImageRep gains a layoutDirection property. layoutDirection may take one of three values: NSImageLayoutDirectionUnspecified, NSImageLayoutDirectionLeftToRight, NSImageLayoutDirectionRightToLeft. NSImageLayoutDirectionUnspecified means that image rep is equally appropriate for left-to-right and right-to-left layout directions. It is the default value for new image reps.

When drawing an NSImage the correct layout direction is inferred based on the prevailing drawing conditions. This is the case for example inside a view's -drawRect: implementation. In some circumstances it is necessary to manually specify the desired layout direction. This can be accomplished by specifying the NSImageHintUserInterfaceLayoutDirection in the hints dictionary passed to NSImage's draw or rep selection methods.


NSColorSpace now includes support for the “display P3” color space, which has standard DCI-P3 primaries, a D65 white point, and the same gamma curve as the sRGB IEC61966-2.1 color space. It is a canonicalization of the new iMac display profiles that is useful for tagging wide color gamut content.
+ (NSColorSpace *)displayP3ColorSpace;
We also have a corresponding convenience constructor in NSColor:
+ (NSColor *)colorWithDisplayP3Red:(CGFloat)r green:(CGFloat)g blue:(CGFloat)b alpha:(CGFloat)a;

NSColorSpace also exposes sRGB color spaces that enable specifying colors outside of the 0..1 range:
+ (NSColorSpace *)extendedSRGBColorSpace;
+ (NSColorSpace *)extendedGenericGamma22GrayColorSpace;
These provide extended versions of existing color spaces sRGBColorSpace and genericGamma22GrayColorSpace.

To provide consistency with UIColor, the behaviors of the following methods (all introduced in 10.9) have been modified to accept extended color component values. If red, green, blue, or saturation, brightness, or white values are outside of the 0..1 range, these will create colors in the extended sRGB or extendedGenericGamma22GrayColorSpace color spaces:
+ (NSColor *)colorWithWhite:(CGFloat)w alpha:(CGFloat)a;
+ (NSColor *)colorWithRed:(CGFloat)r green:(CGFloat)g blue:(CGFloat)b alpha:(CGFloat)a;
+ (NSColor *)colorWithHue:(CGFloat)h saturation:(CGFloat)s brightness:(CGFloat)b alpha:(CGFloat)a;

Finally, we have the following new API in NSColor to enable creation of RGB-based colors from HSB component values using an arbitrary color space. An exception will be raised if the color model of the provided color space is not RGB:
+ (NSColor *)colorWithColorSpace:(NSColorSpace *)space hue:(CGFloat)h saturation:(CGFloat)s brightness:(CGFloat)b alpha:(CGFloat)a;

NSWindow deep buffer support for wide color monitors

On monitors that support wide color, NSWindow automatically increases the default depth of associated backing stores and offscreen buffers. This can be overridden by setting NSWindow.dynamicDepthLimit = NO, and also setting NSWindow.depthLimit to the desired value. The supported depths are NSWindowDepthTwentyfourBitRGB, NSWindowDepthSixtyfourBitRGB, and NSWindowDepthOnehundredtwentyeightBitRGB. NSWindowDepthTwentyfourBitRGB is the historical default value, and the value used for monitors deemed insufficiently wide. NSWindowDepthSixtyfourBitRGB is the new default for wide monitors, like the P3 panels in the current iMacs. AppKit automatically adjusts the bit-depth of layer backing stores to match the window they are hosted in. This can be overridden on a layer by layer basis using CALayer.contentsFormat.

NSImage support for wide color image reps

NSImage will now use colorspace to disambiguate otherwise identical image reps. For example, on a system with Display P3 output colorspace NSImage will favor an NSBitmapImageRep whose colorspace is display P3, over an otherwise identical NSBitmapImageRep whose colorspace is sRGB.

The colorspace of an image rep can be set using the existing colorSpace property of NSBitmapImageRep, or by configuring the appropriate fields in the asset catalog inspector in Xcode.

Colors in RTF Files

Colors are now preserved in RTF files with a lot more fidelity, by recording the color space and writing count components with more precision. Among other things this enables deep colors to be saved in RTF files.

In the WWDC seed, this feature is enabled on OS X only, although it is planned for other platforms in subsequent seeds.

The extensions to the RTF spec that enable this will be published shortly.


The weight for +[NSFont boldSystemFontOfSize:] is changed to NSFontWeightBold to match the instance returned from +systemFontOfSize:weight: with NSFontWeightBold.


The role of -invalidateCharacterCoordinates is clarified in the header comment. NSTextView is updated to adopt the new behavior.


The menu indicator inside the token is now displayed on the left of title when -userInterfaceLayoutDirection is NSUserInterfaceLayoutDirectionRightToLeft.


Just like on iOS, NSLayoutManager now renders NSLinkAttributeName with underlined blue color without any NSTextView attached on OS X for apps linked with 10.12 SDK or later.


With the change for NSLinkAttributeName rendering for NSLayoutManager, NSTextField now renders the link without the field editor.