Skip to content

Instantly share code, notes, and snippets.

@zwaldowski
Last active August 7, 2023 08:34
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zwaldowski/8710fddc8b0b39d2c152 to your computer and use it in GitHub Desktop.
Save zwaldowski/8710fddc8b0b39d2c152 to your computer and use it in GitHub Desktop.
10.9 AppKit Release Notes

OS X Developer Release Notes: Cocoa Application Framework

Notes specific to Mac OS X 10.9

Some of the major topics covered in this section include:

### Sheet Presentation

Sheet API has been moved from NSApplication to NSWindow. In this move, a number of changes to the API have been made. First is the use of blocks as completion handlers, rather than delegation.

Rather than presenting a sheet:

	[NSApp beginSheet:mySheet modalForWindow:docWindow modalDelegate:nil didEndSelector:nil contextInfo:nil];

This will instead be:

	[docWindow beginSheet:mySheet completionHandler:nil];

Likewise, when handling the ending of a sheet, a separate method was needed to act as the endSelector:

	[NSApp beginSheet:mySheet modalForWindow:docWindow modalDelegate:self didEndSelector:@selector(didEndSheet:returnCode:contextInfo:) contextInfo:nil];

	- (void)didEndSheet:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo {
		[sheet orderOut:self];
		NSLog(@"Good bye sheet.");
	}

This will instead be handled in the completionHandler block:

	[docWindow beginSheet:mySheet completionHandler:^(NSModalResponse response) {
		NSLog(@"Good bye sheet.");
	}];

In this example, you’ll also notice that -orderOut: no longer needs to be called in the completion handler. If you do not dismiss the sheet, it will be done for you after the completion handler finishes.

NSModalResponse is a new typedef in NSApplication created with an enum of modal responses. NSModalResponseStop, NSModalResponseAbort, and NSModalResponseContinue are added in replacement of the deprecated NSRunStoppedResponse, NSRunAbortedResponse, and NSRunContinuesResponse.

NSWindow also adds two more modal responses: NSModalResponseOK and NSModalResponseCancel (which are replacements for NSPanel's NSOKButton and NSCancelButton).

A sheet's parent (the window or sheet it is attached to), can now be retrieved with -[NSWindow sheetParent]. This relationship is maintained from the time the sheet is begun with -beginSheet:… to when it is ordered out.

Another change brought by the moving of this API is queued and critical sheets. Previously, attempting to show a sheet on a window that already has a sheet would result in a 'Beep' to the user, a loss of contextInfo's memory, and no return call to the modalDelegate. The new NSWindow API will queue the second sheet if there is already a sheet present on the window. Once the first sheet is ended and ordered out, the second sheet will be brought down. Queued sheets can be ended ahead of time; so that if a queued sheet becomes unnecessary before the current sheet ends, the queued sheet doesn't have to be presented later. Critical sheets are sheets that are time sensitive and critical to the user; these will skip the queue and be presented on top of an existing sheet, if necessary. Sheets attempted to be presented while a critical sheet is up will be queued like normally; and after the critical sheet is dismissed, the previously presented sheet and queued sheets will be able to be interacted with again.

NSApplication's sheet API will continue to work as it did before, without the ability to queue sheets.

NSAlert's -beginSheetModalForWindow:modalDelegate:didEndSelector:contextInfo: has been deprecated in favor of -beginSheetModalForWindow:completionHandler:. Through its use of NSWindow's new sheet API, alerts with an alert style of NSCriticalAlertStyle will be presented as critical sheet.

NSAlertFirstButtonReturn, etc are marked as additional NSModalResponses used by -beginSheetModalForWindow:completionHandler: and -runModal. -[NSAlert runModal] is declared as returning an NSModalResponse (a typedef of NSInteger).

NSAlert's Functional API and -alertWithMessageText:defaultButton:alternateButton:otherButton:informativeTextWithFormat: has been deprecated. These creation methods have used different return codes from modern alert API; these old return codes (NSAlertDefaultReturn, NSAlertAlternateReturn, etc.) are also deprecated. NSAlert and its properties should be used to create an alert instead.

Controls' -stringValue

NSSlider, NSStepper, and NSLevelIndicator use the set NSFormatter to format the result of -stringValue as well as retrieve the value set through -setStringValue:.

If there is no set formatter, the value is formatted to an NSString with %g.

NSClipView

Before 10.9, overriding -constrainScrollPoint: aided in allowing developers to center (or use any custom positioning) a document within a scroll view. This works for constraining scrolling; however, constraining the changes resulting from an animation of a change in magnification requires knowledge of the size of the bounds. For this, NSClipView now has -constrainBoundsRect:. This comes with the deprecation of -constrainScrollPoint:, as it can handle a superset of the problems that -constrainScrollPoint: could.

NSMatrix

The order of cells in NSMatrix is right-to-left layout when -[NSApplication userInterfaceLayoutDirection] returns NSUserInterfaceLayoutDirectionRightToLeft. This can be disabled or forced in IB by switching the Control's 'Mirror' value in IB.

NSPrinter

PPD access is deprecated through NSPrinter's table methods (-statusForTable:, -stringForKey:inTable:, etc). PMPrinter API should be used instead.

NSSlider

NSSliderCell exposes API to support appearance customization:

  • -drawTickMarks is an override point to customize the drawing of tick marks.
  • -barRectFlipped: returns the rectangle in which the slider bar is drawn.
  • Overriding -drawBarInside:flipped: will actually override bar drawing.
  • NSSliderCell's -knobRectFlipped: can be called directly if needed.

On apps linked against 10.9, the values returned by the dimensional methods (and passed into the drawing methods) are fitted to the size of default slider artwork. Any custom sliders should be sure to either override the dimensional methods with valid results for their custom artwork, or at the very least consider this fitting inside of -drawBarInside:flipped: and -drawKnobInside:flipped:. The dimensions returned by the default slider cell may also change in future releases, so they should not be assumed to remain constant. For binary compatibility, in apps linked before 10.9, NSSliderCell’s methods return and are passed the legacy, non-fitted rects.

Linear NSSliders now support right-to-left configuration when -[NSApplication userInterfaceLayoutDirection] returns NSUserInterfaceLayoutDirectionRightToLeft. This can be disabled or forced in IB by switching the Control's 'Mirror' value in IB.

NSSliderCell no longer receives an additional call to -continueTracking after the -stopTracking call.

NSSlider and NSSliderCell have formal deprecations for previously obsolete methods:

  • -setImage:
  • -image
  • -setKnobThickness:
  • -setTitleCell:
  • -titleCell
  • -setTitleColor:
  • -titleColor
  • -setTitleFont:
  • -titleFont
  • -setTitle:
  • -title
### `NSStackView`

NSStackView is a new class in OS X 10.9. It is used to layout horizontal or vertical stacks of views using auto layout. Necessary constraints will automatically be created and modified when adding and removing views from a stack view to maintain a cohesive layout. This behavior is extended by customizing various properties of the stack view and the views it holds. Decreasing the clipping resistance priority allows the stack view to become smaller than the the minimum required to hold the provided views. Depending on the visibility priority associated with the internal views, they may either overflow and clip off the side, or drop from the view hierarchy. These dropped views are still retained by the stack view, and will be reattached if the stack view becomes the necessary size. Views can be forced to be dropped or reattached by setting the necessary visibility priority.

Note that NSStackView's hugging and clipping resistance priorities are distinct from NSView's contentHugging and compression resistance priorities. Since stack views have no intrinsic content sizes, contentHugging does not affect it. However, NSStackView's hugging priority is the priority at which the StackView wants its internal spacing to be at a minimum and "hug" its contained views. The clipping resistance priority is used to prevent the clipping of the contained views; a value less than NSLayoutPriorityRequired means the stack view can become less than the minimum size required to hold all of the its views.

Keep in mind that the default hugging priority of NSStackView is NSLayoutPriorityDefaultLow (250).  If you add views with hugging priorities of the same value, the constraints can be ambiguous, causing unexpected layouts such as oddly wide or tall views.  Fixing these issues can be as simple as tweaking the stack view’s hugging priority, the view’s content hugging priority, or by adding explicit size constraints on the view.

The view hierarchy that NSStackView manages is private. Additional subviews and constraints can be added to the stack view itself, but should not be added to its private views. These views should not be assumed to remain consistent in future releases, nor should they be assumed to be encoded or decoded with NSCoder. Because external constraints can be added to the views you add to a stack view, there should be no need to manipulate or measure these private views.

NSTabView uses the contentCompressionResistancePriority in the orientation of the tabs to prevent clipping of tabs. Top and Bottom tabs will use the horizontal contentCompressionResistancePriority; left and right tabs will use the vertical contentCompressionResistancePriority.

NSWindow

NSUnscaledWindowMask is formally deprecated.

### Application and Window Occlusion

AppKit has a new API to notify an application if its windows are visible to the user on screen. If a window is not visible to the user then it is occluded.

There are two sets of methods; one set on NSApplication and one set on NSWindow. Both sets include a delegate method, an NSNotification, and a method to query the current state. To determine if any part of your application is visible, your application delegate can implement the method like this:

- (void)applicationDidChangeOcclusionState:(NSNotification *)notification
{

	if ([NSApp occlusionState] & NSApplicationOcclusionStateVisible) {

		// Visible

	} else {
		// Occluded

	}

}

When the delegate method is called or the notification is posted, use either -[NSApplication occlusionState] or -[NSWindow occlusionState] to retrieve the current occlusion state of the application or window. Note that the result of this method is a bitfield, so the appropriate way to check for visibility is to use the bitwise-AND operator. Do not use the equality operator.

Windows are considered occluded if their entire content, including title bar and tool bar, is 100% covered by another opaque window. Windows are also occluded if they are ordered off screen, minimized to the dock, or on another space. Partial occlusion counts as “visible.” An application is only considered occluded if all windows owned by the application are occluded. That is, if any part of any window is visible, then the application is visible.

If your application has no windows except the menu bar, then your application is considered occluded. However, if your application uses an NSStatusItem, then the window that displays the status item is considered owned by your application and your application will not become occluded while the status item is visible.

This API can be used for increasing the performance of your application, including power, CPU, and network efficiency. For example, when your application is invisible to the user, it might cease expensive operations like retrieving data over the network or drawing an animation. You may also decide to trigger the start of expensive work when notified that the application or window has become visible.

The system reserves the right to delay notification of visibility during certain performance-critical periods. For example, exposing all windows on the system when the user enters Mission Control. In these cases the system will favor responsiveness to the user, and applications will be notified after the performance critical period has finished.

In 10.9, NSMenu has better support for views using auto layout. If the top-level view set on the menu item has translatesAutoresizingMaskIntoConstraints set to NO, the menu item will establish a required LeadingX constraint that position the view in the menu, and another required width constraint that sizes it equal to the menu. The height is the responsibility of the view.

If translatesAutoresizingMaskIntoConstraints is YES, the behavior is as it was in previous releases.

Auto Layout and window resize cursors

Window resize cursors now correctly reflect the minimum and maximum window sizes as determined by auto layout.

-[NSPopUpButtonCell cellSize]

NSPopUpButton's cellSize method no longer considers the width of the key equivalent, which has never been drawn in OS X anyways.

View-based NSTableView scrolling optimized under Auto Layout

In 10.9, View-based NSTableViews have been optimized under auto layout to improve scrolling performance. To take advantage of the optimization, do not establish constraints that relate a view within an NSTableView row to a view outside of the NSTableView. (This would be difficult to do in any case - if you design your table view rows in IB you should be fine.)

+[NSApplication setActivationPolicy:]

In 10.9, +setActivationPolicy: now supports NSApplicationActivationPolicyAccessory.

-[NSWorkspace openURL:]

In 10.9, -[NSWorkspace openURL:] may show an error dialog on failure, for apps linked using the 10.9 SDK or later. The return value of -openURL: is unaffected.

NSWindow implicit animations

For apps compiled with the 10.9 SDK, -[NSWindow setFrame:display:] and -[NSWindow setFrameOrigin:] now perform animations, if invoked in an implicit animation context. To opt out, invoke -[NSWindow setFrame:display:animate:] and pass NO for the animate parameter.

Full screen NSToolbar changes

Before 10.9, NSToolbar would ignore the fullScreenAccessoryViewMinHeight when NSApplicationPresentationAutoHideToolbar is set. In 10.9, setting a fullScreenAccessoryViewMinHeight will cause it to be respected whether AutoHideToolbar is set or not. If you set a value of 0, the accessory view will animate in and out as the menu bar animates in or out.

Status Items with multiple menu bars

10.9 introduces multiple menu bars, each of which draws the status items. If your status item has a custom view, this view is positioned in one menu bar, and other menu bars get a “clone”, which looks identical. The clones are not exposed in the API.

The clones are drawn by redirecting your custom view’s drawing into another window. This means that your status item should not make assumptions about the drawing destination. For example, it should not assume that a call to -drawRect: is destined for the view’s window, or that the resolution of the drawing destination matches the resolution of the status item’s screen. You must also not assume that the status item is on any particular display, except as described below.

The clones are only redrawn in NSDefaultRunLoopMode. This allows the status item to limit highlighting to one display, by driving the run loop in another mode, such as NSEventTrackingRunLoopMode. For example, if you wish to simulate a menu, you would implement mouseDown: to show your window, and run the run loop in NSEventTrackingRunLoopMode until you determine that the window should be dismissed. While the run loop is in this mode, only the true status item will redraw. Clone status items will not redraw, and therefore they will not show any highlight applied to the true status item.

When a clone status item is clicked, the clone exchanges locations with the true status item. This means that the location and screen of the status item window is reliable from within -mouseDown:. You can access this information from your custom view, for example, using [[view window] screen] to position a window on the same screen as the status item.

NSSegmentedControl now better respects -sendActionOn:

In 10.9, segmented controls that have -sendActionOn: set to NSLeftMouseDownMask now work correctly.

-constrainFrameRect:toScreen: now invoked for borderless windows

Prior to 10.9, the NSWindow method -[NSWindow constraintFrameRect:toScreen:] was invoked only for windows with NSTitledWindowMask set in their styleMask. In 10.9, this method is invoked for all windows. The default implementation does a more limited constraining for non-titled windows, as described in “NSWindows constrained to not intersect the menu bar” below.

### `NSWindow`s constrained to not intersect the menu bar

In 10.9, in support of the new multi-monitor architecture, windows are now constrained to not intersect the menu bar on their containing space. This restriction was already in place for titled windows, but it has been extended to borderless windows whose level is at least NSNormalWindowLevel but less than NSMainMenuWindowLevel. This behavior is implemented in -[NSWindow constraintFrameRect:toScreen:]. You may override that method in an NSWindow subclass to adjust or prevent this constraining.

### `NSNibLoading`

The following nib loading methods on NSBundle and NSNib have been formally deprecated:

  • +[NSBundle loadNibFile:externalNameTable:withZone:]
  • +[NSBundle loadNibNamed:owner:]
  • -[NSBundle loadNibFile:externalNameTable:withZone:]
  • -[NSNib initWithContentsOfURL:]
  • -[NSNib instantiateNibWithExternalNameTable:]
  • -[NSNib instantiateNibWithOwner:topLevelObjects:]

The ARC-compatible methods introduced in 10.8 should be used instead:

  • -[NSBundle loadNibNamed:owner:topLevelObjects:]
  • -[NSNib initWithNibData:bundle:]
  • -[NSNib instantiateWithOwner:topLevelObjects:]

It is important to note the difference in memory management between the deprecated and new methods. The deprecated methods retained the top level objects of the loaded nib file, requiring the caller to explicitly release them. This is no longer necessary with the new methods because they follow the standard Cocoa memory management rules and autorelease the top level objects. IBOutlet properties to top level objects should be strong (retain) to demonstrate ownership and prevent deallocation. Alternatively, one may hold a strong reference to the top level objects array, available as an out parameter on these methods.

### Sharing Service

In 10.9, NSSharingService provides some new built-in services:

NSString * const NSSharingServiceNamePostOnTencentWeibo;
NSString * const NSSharingServiceNamePostOnLinkedIn;
NSString * const NSSharingServiceNameUseAsFacebookProfileImage;
NSString * const NSSharingServiceNameUseAsLinkedInProfileImage;

In addition NSSharingService provides the following new properties:

@property (copy) NSString *menuItemTitle;
@property (copy) NSArray *recipients;
@property (copy) NSString *subject;
@property (readonly, copy) NSString *messageBody;
@property (readonly, copy) NSURL *permanentLink;
@property (readonly, copy) NSString *accountName;
@property (readonly, copy) NSArray *attachmentFileURLs;
### Responsive Scrolling

Mac OS 10.9 has a new feature called Responsive Scrolling. Responsive Scrolling allows the application to continue to rapidly scroll content even when the application’s main thread is busy doing other work. AppKit accomplishes this by having the document view draw more than what is currently visible during idle (see the Overdraw section in these release notes). The responsive scrolling thread is then free to replace what is on the screen with this previously drawn content. Responsive Scrolling requires one to use an NSScrollView, NSClipView and a document view.

By default, AppKit tries to turn on this feature where applicable. The following primary conditions, however, are not compatible with Responsive Scrolling. If any of the following conditions are met, the traditional scrolling behavior is performed.

  • The application is primarily a Carbon application
  • The documentView has an OpenGL context
  • The window alpha is not 1.0
  • The application links on 10.7 or prior (the application must link on Mountain Lion or higher to support this feature)

There are some secondary requirements that your NSScrollView subclass, NSClipView subclass, or document view must meet for them to be eligible for Responsive Scrolling. These secondary requirement checks may be bypassed by overriding the following new NSView class method on the view that fails the secondary requirements. You should strive to meet the requirements and only use this override as a last resort.

@interface NSView ()
+ (BOOL)isCompatibleWithResponsiveScrolling;
@end

The list of secondary requirements are:

  • Do not override -scrollWheel: in an NSScrollView, NSClipView subclass, or in the document view. (See the event modal notes in this section)
  • Do not override -drawRect: in an NSScrollView subclass
  • Do not override -lockFocus: in an NSScrollView, NSClipView subclass, or in the document view.

Layer backed secondary requirements:

  • The root layer must be either the NSScrollView or an ancestor view

Traditional drawing secondary requirements:

  • copiesOnScroll must be set to YES on the NSClipView
  • The documentView must override -isOpaque and return YES
#### Event Modal

Traditionally, each scroll wheel event is uniquely hit tested and then handled. For non-gesture scrolling devices, this is still true. For gesture scrolling devices, this has changed dramatically. Once NSScrollView receives a scroll wheel event, it goes into a concurrent tracking loop. That is, future scroll wheel events are captured privately and processed on a background thread until the gesture, and any associated animation, is complete. If the user physically performs a consecutive scroll gesture, for responsive tracking purposes, it is considered a continuation of the current gesture and is therefore not hit tested.

You may be able to replace your NSScrollView, NSClipView subclass, or document view -scrollWheel: override with one or more of the following techniques.

  • Register for bounds change notifications on the clip view
  • Register for the live scroll notifications (see the the ScrollView section)

If you only need to peek at the initial scroll wheel event, then return YES from +isCompatibleWithResponsiveScrolling to explicitly opt in to Responsive Scrolling.

While the scroll wheel events are being processed on a background thread, the main thread is periodically requested to synchronize. During this synchronization, the clip views bounds are updated and any required notification are posted. If the main thread is free, it is also asked to perform additional overdraw in the direction of the scroll (see NSScrollView - Overdraw). The result is that if the main thread is busy and / or cannot synchronize quickly enough, the visibleRect of the document may differ from what the user sees on screen. Also, if there is no existing overdraw content at the scrolled to location, then concurrently moving the content is paused while waiting for the main thread to catch up.

### `NSScrollView` - Live Scroll Notifications

NSScrollView posts new notifications in response to user initiated scrolling. This may occur due to scroll wheels, scroll gestures, scroller tracking or page up / down animation. These notifications are sent on the main thread.

NSString * const NSScrollViewWillStartLiveScrollNotification;
NSString * const NSScrollViewDidLiveScrollNotification;
NSString * const NSScrollViewDidEndLiveScrollNotification;

If the user action has a known start and end point, the WillStart and DidEnd notifications are issued with 0 or more Did notifications sent in between. If the scroll is an animation (for example rubber banding), the DidEnd notification is not sent until the animation completes. If the scroll view is performing Responsive Scrolling, multiple consecutive scrolling gestures are grouped together into a single series of LiveScroll notifications bracketed by a single WillStart / DidEnd pair.

Some subviews of the document view do not scroll with the rest of the document. Instead these views appear to float over the document (see NSTableView floating group rows). The following API makes it easier to work with these types of floating views. Also, NSScrollView ensures that any scrolling on the non-floating axis is visually performed synchronously with the document content. Note: You are responsible for keeping track of the floating views and removing them via -removeFromSuperview when they should no longer float. A view may only float on one axis at a time.

- (void)addFloatingSubview:(NSView *)view forAxis:(NSEventGestureAxis)axis;
### `NSScrollView` - Overdraw

To facilitate Responsive Scrolling, your document view will be asked to draw portions that are not currently visible to the user. AppKit balances the amount of non-visible content drawn with the amount of memory and power usage such drawing requires. NSScrollView is then free to visually scroll to any previously overdrawn content during Responsive Scrolling.

If your document view has multiple subviews or you need more control over the overdraw area, your document view needs to implement the methods to ensure that all the appropriate content exists in the requested overdraw area.

The following method is called by NSView with a rect for a recommended area that should be fully rendered for overdraw. Override this method and bring in additional subviews and pre-cached content for the rect in order to perform responsive scrolling. Calling super may be required for some subclasses (such as NSTableView and NSOutlineView), so in general, super should always be called. To suppress overdraw for a particular view (such as NSTableView), override this method and call [super prepareContentInRect:[self visibleRect]].

- (void)prepareContentInRect:(NSRect)rect;

The preparedContentRect is the area of the NSView that has full content coverage. In general, this should be called with the area that is filled in fully with views. It should always include the visibleRect. Set this with a value equal to the visibleRect to have overdraw start from the visibleRect and automatically grow larger on idle, as is needed for optimal system performance.

@property NSRect preparedContentRect;

-[NSApplication stopModal] and -[NSApplication stopModalWithCode:] can now be called from an NSTimer or other runloop source. This lifts the restriction requiring abortModal to be used in these cases.

NSWindow.styleMask

AppKit reserves the right to use all bits of the styleMask in NSWindow, and some are used for private communication with other Apple frameworks. Please do not use undocumented styleMask bits for your own NSWindow subclasses.

### Spaces and Multiple Screens

In 10.9, we have added a feature where each screen gets its own set of spaces, and it is possible to switch between spaces on one screen without perturbing the spaces on the other screens. In this mode, a fullscreen window uses one screen, and leaves the contents of any other screens unchanged.

Each screen now has its own menu bar, and it is possible to show the Dock on any screen, provided you have the Dock set to “Position on Bottom”.

The menu bar has an active appearance on the active screen, which is typically the screen containing the key window. Menu bars on other screens have an inactive appearance.

In this mode, it is desirable for new windows to open on the active screen. In support of this model, +[NSScreen mainScreen] now returns the active screen, which is slightly different than its prior behavior of returning the screen containing the keyWindow, if any, and the zero screen otherwise.

A window restored at app launch through -restoreStateWithCoder: will return to its previous location, independent of active screen. A window positioned using -setFrameAutosaveName: will prefer the active display.

This feature can be disabled by unchecking the preference named “Displays have Separate Spaces” in the Mission Control preference pane in System Preferences. This setting only takes effect after logging out and back in, or restarting. NSScreen has API to query whether the separate space feature is enabled:

+ (BOOL)screensHaveSeparateSpaces NS_AVAILABLE_MAC(10_9);

When this feature is enabled, windows may not visibly span displays.  A window will get assigned to the display containing the majority of its geometry if programmatically positioned in a spanning position.  A window will get assigned to the display containing the mouse if the window is moved by the user.  A window clips to the edge of the display, whether or not there is another adjacent display.

### Tagging Support in `NSSavePanel`

NSSavePanel provides a field that allows users to specify Tags (a new feature in OS X 10.9) that should be applied to the resulting file. However, since NSSavePanel isn't responsible for creating the file, your application should adopt new API to ensure the requested Tags are set correctly.

To opt in to NSSavePanel Tagging support, you should invoke -[NSSavePanel setShowsTagField:YES] prior to displaying the panel. When the user click Save in the panel, you can get the Tag names they entered by invoking -[NSSavePanel tagNames]. After creating the file at the requested URL, you should set the requested Tag names on the file by using the NSURLTagNamesKey API.

If your application does not adopt the above API, NSSavePanel will still show the Tags field and will attempt to automatically apply the Tags by listening to file system change notifications for a limited duration to detect when your application creates the requested file. However, this technique is imperfect, so you are strongly encouraged to test your application's support for tags in the save panel and adopt the above API if needed.

### Export as PDF

In OS X 10.9, NSDocument and NSPrintOperation provide new API and functionality to aid you in creating an Export as PDF option that is consistent with the rest of the operating system.

NSDocument has a new standard IBAction method called -saveDocumentToPDF:. If your NSDocument subclass already implements -printOperationWithSettings:error:, then invoking this method will cause NSDocument to use the resulting NSPrintOperation to prompt the user for a location and save a PDF. The resulting PDF export panel will also include certain standard print panel configuration controls that you have enabled (like paper size and orientation) and the first accessory controller from the NSPrintOperation's NSPrintPanel.

The default implementation of -saveDocumentToPDF: simply invokes [self printDocumentWithSettings: @{ NSPrintJobDisposition : NSPrintSaveJob} showPrintPanel:NO delegate:nil didPrintSelector:NULL contextInfo:NULL]. When invoked with these parameters, the method will invoke -PDFPrintOperation instead of -printOperationWithSettings:error:. The default implementation simply invokes [self printOperationWithSettings:@{ NSPrintJobDisposition : NSPrintSaveJob } error:NULL], but you can override this method if you need to customize the way your application creates PDFs or to provide a different accessory controller.

If your application doesn't use NSDocument, you can still use NSPrintOperation to implement Export as PDF. Prior to OS X 10.9, running an NSPrintOperation that had its job disposition set to NSPrintSaveJob and its NSPrintJobSavingURL set to nil would result in undefined behavior. However, on OS X 10.9, doing this will cause NSPrintOperation to display an NSPDFPanel, prompting the user for a location where it will save the PDF.

Whether or not you use NSDocument, you can modify the PDF export panel used by NSPrintOperation by either creating a new NSPDFPanel with the desired options and accessory controller, or modifying the one that NSPrintOperation creates automatically.

If your application is unable to use NSPrintOperation to generate PDFs, you can still use NSPDFPanel to ensure your application's user interface is consistent with the rest of the operating system. In order to do this, you should first create an NSPDFInfo object, optionally changing the paperSize and orientation properties. Then you should invoke -[NSPDFPanel beginSheetWithPDFInfo:modalForWindow:completionHandler:] passing the NSPDFInfo object you created. When the completion handler is invoked, the given NSPDFInfo object will be modified with the URL, file extension hidden flag, and Tag names, and rendering parameters that should be used when creating the PDF.

Shoebox-like applications may wish to generate multiple separate PDFs when the user has selected multiple items. To support this, NSPDFPanel supports the NSPDFPanelRequestsParentDirectory option. When run with this option, NSPDFPanel will prompt the user to choose a directory instead of a directory and a document name. The URL of the resulting NSPDFInfo object will contain the user's chosen directory. You are responsible for appending a file name to this path.

If your application manually runs an NSPDFPanel but uses NSPrintOperation to create PDFs, NSPrintInfo provides -takeSettingsFromPDFInfo:, which will modify the receiving NSPrintInfo with all the settings from the given NSPDFInfo. But remember, if you use NSPDFPanelRequestsParentDirectory, you must modify the NSPDFPanel's URL by appending a file name before passing it to -takeSettingsFromPDFInfo:. If the URL doesn't looks like it points to a directory, the method will throw an exception.

NSDocument provides the -performActivityWithSynchronousWaiting:usingBlock: to ensure document concurrent operations are performed and their results presented in a properly serialized manner. Presentation of any alert or error sheet on a document is supposed to be done within an 'activity' block to avoid multiple sheets interfering with each other.

NSDocument internally presents many alerts on documents and is responsible for making sure this is done within an 'activity' block. However, prior to OS X 10.9, the alert that is displayed when the user edits a locked document was not presented within an 'activity' block. As a result, alerts originating from application-defined 'activities' could potentially interfere with it, often resulting in deadlocks. This has been fixed on OS X 10.9.

Bug Fixes for NSPathControl in Sandboxed Applications

Prior to OS X 10.9, NSPathControl behaved unexpectedly in sandboxed applications when used with a URL within the user's home directory. NSPathControl would fail to recognize that sandboxing redirects NSHomeDirectory() to the application's sandbox container. Additionally, the NSPathControl was given the URL to the user's real home directory, it would fail to recognize that path as home, and would therefore show the entire path up to the root of the volume instead of stopping at the user's home directory. These issues have been fixed on OS X 10.9.

NSSavePanel / NSOpenPanel

Key Value Observation compliance was dramatically increased for public and some private properties of actual, non sandboxed NSOpen and Save panels, including keys affecting other values. For example, if the directory value changes on a save panel, this will cause a KVO notification to be emitted for the URL value as well as the directory value. Sandboxed NSOpen and Save Panels do not have the same level of KVO compliance.

In the “On my Mac” mode of the App Centric Open Panel (the open panel shown for applications using iCloud), accessory Views are now hidden by default in and can be revealed by hitting the “Options…” button.

Automatic key loop recalculation is enabled. This not only obviates the need to explicitly recalculate the key loop after modifying a subview of the accessory view but also makes it possible for the accessory view itself to reliably declare itself a key view.

Specification of fonts in nib files

The name of the default system font has changed from LucidaGrande to .LucidaGrandeUI.  In the vast majority of cases this should not present a problem.  However, there is a case where fonts can be unexpectedly decoded from an archive as LucidaGrande rather than the new system system font.  This can cause a variety of subtle issues, including slight changes to the layout of certain button titles.  This will occur if you are still using nib files rather than xib files, built them using Xcode 4 or earlier, and they use system fonts in non-standard point sizes. When you change the point size to be non-standard, older versions of Xcode will change the displayed font type from "System" to "Custom", and then it will not be decoded as the new system font on Mavericks. Xcode 5 will correct this problem when opening your nib file, so the UI will automatically show "System", but note that it's still necessary to save the changes.

NSSound

Channel mapping is deprecated in 10.9, consequently channels should be mapped at a lower level using AudioUnitSetProperty.

Event-specific behavior of -isSwipeTrackingFromScrollEventsEnabled

In 10.9, the user may choose to have different preferences for the “Swipe between pages” behavior for mouse and trackpad input devices. It is now possible for this behavior to be enabled for trackpad devices but disabled for mouse devices (or vice versa). By default, swipe between pages is enabled for trackpads and disabled for mice.

AppKit provides the -isSwipeTrackingFromScrollEventsEnabled method to determine the current user preference. The behavior of this method is now based on the current event (as returned by [NSApp currentEvent]). If the current event originated from a mouse device, this method returns the user preference for mouse devices; otherwise, it returns the user preference for trackpad devices.

New Accessibility constants

These accessibility constants have been added:

NSAccessibilityMarkedMisspelledTextAttribute

NSAccessibilityMisspelledTextAttribute was the original attribute to indicate misspelled text. In OS X 10.4, the Cocoa text system added support for NSAccessibilityMarkedMisspelledTextAttribute, which was used to indicate a word that was visibly marked as misspelled (for example, with a red squiggle underneath); the original MisspelledText attribute could also be used on text that was not visibly marked as misspelled (for example, a misspelled word that was currently being edited by the user).

Typically, a screen reader only wants to vocalize what a sighted user could see, and so the MarkedMisspelledText attribute was adopted by VoiceOver to provide feedback to the user about misspelled text. In OS X 10.9, VoiceOver has entirely stopped using the original MisspelledText attribute, and now only checks for MarkedMisspelledText.

When implementing accessibility for a custom text-editing engine, you should generally provide the MarkedMisspelledText attribute in order to support VoiceOver, especially in OS X 10.9 and later. You may optionally also support the MisspelledText attribute for compatibility with other accessibility clients.

NSAccessibilityDescriptionListSubrole

This subrole is similar to the existing NSAccessibilityDefinitionListSubrole, but is preferred to represent HTML5 objects indicated by the <DL> tag.

Accessibility Notification support for custom accessible objects

The NSAccessibility informal protocol now supports a new protocol method, -accessibilityNotifiesWhenDestroyed.

Prior to 10.9, the only accessible objects that could post accessibility notifications were those that inherited from NSView, NSWindow, or NSCell. An application's custom accessible object, subclassed from NSObject, could not post notifications.

In 10.9 and later, an application's custom accessible object may post accessibility notifications if it follows the following guidelines:

  • the object must implement -accessibilityNotifiesWhenDestroyed to return YES.

  • the object must post the NSAccessibilityUIElementDestroyed notification at appropriate times, typically when the corresponding UI element in the application's visual interface is removed from the screen, and certainly when the accessible object is deallocated.

  • the lifetime of the NSObject must match the lifetime of the corresponding element in the application's visual interface. It is common for a custom accessible object that acts as a proxy for an onscreen UI element to be autoreleased and deallocated very quickly, immediately after the application responds to a single accessibility request. This is not sufficient to support posting notifications, because any notification observers that are registered on the object will be removed as soon as the object is deallocated. Instead, the application must arrange for an accessible object that refers to a specific UI element to remain allocated as long as that UI element is visible.

Accessibility protected content

The Accessibility API is designed to help make OS X more accessible to users with disabilities. To accomplish this, the API is able to vend all of the strings and values that are displayed onscreen to clients such as VoiceOver. This is critical, especially for book-reading applications, because it allows users who are blind to read and interact with the same content as everyone else.

However, some applications need to be able to prevent their string content from being copied by other applications that use the Accessibility API. It is now possible for an application to tell the Accessibility implementation that some of its content is protected.

There are two steps required to indicate that a particular UI element has protected content:

  • use the NSAccessibilitySetMayContainProtectedContent API to indicate that this application contains protected content
  • handle requests for NSAccessibilityContainsProtectedContentAttribute in your accessible objects’s -accessibilityAttributeValue: implementation, returning an NSNumber containing YES.

Accessibility API for transient UI

Application UI elements can appear, disappear, or change as a result of mouse movement to certain positions in the content, or other types of user input, such as press or release of a modifier key. This presents several problems for clients of the Accessibility API:

  • there is no equivalent accessible way to simulate such mouse triggered events
  • there's no way to know when/what happened as a result of mouse rollover

The Accessibility API now offers new features to support transient UI elements.

NSAccessibilityShowAlternateUIAction

NSAccessibilityShowDefaultUIAction

These accessibility actions should be implemented to present the alternative or default UI.

NSAccessibilityPostNotificationWithUserInfo

This API allows an accessibility notification to be posted with a user info dictionary. When transient UI elements are shown or hidden, an application should use this API to post NSAccessibilityLayoutChangedNotification with a user info dictionary containing a list of the UI elements that have changed.

NSAccessibilityLayoutChangedNotification

This notification lets accessibility clients such as VoiceOver know that some UI layout change has occurred. The client application then has the option to decide if it wants to give feedback, auto jump to a new UI, list the new or changed UIs in a menu, or do nothing. The notification can be used by anything that changes UI on screen. As an example, this could be triggered by an explicit NSAccessibilityShowAlternateUIAction, or by user input such as mouse hovering. Similarly, performing NSAccessibilityShowDefaultUIAction or mouse exiting a UI element to revert some transient UIs should also cause this notification to fire. The notification can contain a user info dictionary with the key NSAccessibilityUIElementsKey and an array of elements that have been added or changed as a result of this action.  

NSAccessibilityAnnouncementRequestedNotification

This notification allows an application to request that an announcement be made to the user by an accessibility client such as VoiceOver. The notification requires a user info dictionary with the key NSAccessibilityAnnouncementKey and the announcement as a localized string. In addition, the key NSAccessibilityAnnouncementPriorityKey should also be used to help accessibility clients determine the important of this announcement. This notification should be posted for the application element.

NSAccessibilityUIElementsKey

This key is used in the user info dictionary for notifications. The value is an array of elements that are associated with the notification.

NSAccessibilityPriorityKey

This key can be used in the user info dictionary for any notification. This gives the client an opportunity to determine how to handle this notification based on the priority. For example, a developer can pass the priority for NSAccessibilityAnnouncementRequestedNotification. Clients such as VoiceOver can then decide to speak the announcement immediately or after the current speech is completed. The NSAccessibilityLayoutChangedNotification is another example where priority can help VoiceOver determine if the UI change requires the VO cursor to go to the new UI.

NSAccessibilityAnnouncementKey

This key is used in the user info dictionary for notifications. The value is a localized string. This should generally be used in conjunction with the NSAccessibilityPriorityKey to help accessibility clients determine the important of this announcement.

NSAccessibilitySharedFocusElementsAttribute

Returns an array of elements that also have keyboard focus when a given element has keyboard focus. A common usage of this attribute is to report that both a search text field and a list of resulting suggestions share keyboard focus because keyboard events can be handled by either UI element. In this example, the text field would be the first responder and it would report the list of suggestions as an element in the array returned for NSAccessibilitySharedFocusElementsAttribute.

### `NSAppearance`

NSAppearance is a new class in Mac OS X 10.9. It can be used to access alternate appearances of standard system windows and views. You obtain an NSAppearance by name using +[NSAppearance appearanceNamed:]. A new appearance for controls that is appropriate for light backgrounds (such as popovers) is accessible via the name NSAppearanceNameLightContent. To access the default system NSAppearance, use the name NSAppearanceNameAqua.

NSAppearanceCustomization is a new protocol that NSView and NSWindow adopt that allows customization on those objects. To customize the appearance of a window, call -setAppearance: on the window with your NSAppearance object. That will cause the window itself to take on the customizations in that NSAppearance, as well as any view in that window. To customize just a view, call -setAppearance: on that view. Any specific customization not found in a view's appearance will fall back up to that view's superview, ultimately trying the window's appearance. If a customization is not found at the window level, the default (Aqua) appearance is used. Use the effectiveAppearance method (part of NSAppearanceCustomization) to access what NSAppearance object will be used when drawing that view or window; this takes into account appearances set on superviews and windows.

While drawing views, the +currentAppearance is set for the drawing thread. To access the current appearance, use:

NSAppearance *currentAppearance = [NSAppearance currentAppearance];

Mac OS X 10.9 now contains global user preference settings for the use of automatic quote and dash substitution. Applications that provide for the entry of free-form text in which typographically correct quotation marks and other punctuation would be appropriate may follow these settings by using the new NSSpellChecker methods

+ (BOOL)isAutomaticQuoteSubstitutionEnabled;
+ (BOOL)isAutomaticDashSubstitutionEnabled;

and by listening to the following notifications to be notified of changes

NSString *NSSpellCheckerDidChangeAutomaticQuoteSubstitutionNotification;
NSString *NSSpellCheckerDidChangeAutomaticDashSubstitutionNotification;

For applications compiled on 10.9 and later, NSTextViews by default will automatically follow these settings, unless -setAutomaticQuoteSubstitutionEnabled: or -setAutomaticDashSubstitutionEnabled: has been called.

### `NSTableView`/`NSOutlineView` General Updates

Prior to 10.9, deselecting a row with a cmd-click would call -tableView:selectionIndexesForProposedSelection: but the resulting selection may not have been used. This has been properly fixed for applications that link on 10.9 and higher, and the resulting selection returned by the delegate will be used.

NSOutlineView now fully supports Right To Left language layout. This can be achieved in several ways. One can explicitly set the userInterfaceLayoutDirection in code or in a NIB. Or, if auto-localization is used and the app is linked on 10.9 (or higher), then the userInterfaceLayoutDirection will automatically be flipped if it differs from [NSApp userInterfaceLayoutDirection].

Prior to 10.9, calling -moveRowAtIndex:toIndex: when the NSTableRowView being moved (or any subview of the NSTableRowView) was the first responder, would leave the table in a bad state. This has been fixed for all applications in 10.9. For applications that need to run on platforms prior to 10.9, it is recommended to first make the window the firstResponder before calling -moveRowAtIndex:toIndex: (if the row being moved is the firstResponder).

Prior to 10.9 there was a visual glitch (specifically, a removed NSTableRowView) when performing a row delete right before a row insertion in the same -beginUpdates/-endUpdates block, but only when both animations where either NSTableViewAnimationSlideUp or NSTableViewAnimationSlideDown. This has been fixed for 10.9, and applications that need to target prior to 10.9 should ensure they do a different animation for the deletion, or perform the deletion in a separate -beginUpdates/-endUpdates block.

Using a View Based TableView with a rowSizeStyle of NSTableViewRowSizeStyleDefault will automatically update the rowSizeStyle of each cell view for tables with the NSTableViewHighlightStyleSourceList. However, prior to 10.9 the rowSize style for "header rows / group rows" would always be set to Medium and Large, when they should always be Small regardless of the user setting in System Preferences. This has been fixed in 10.9 for all applications using a View Based TableView.

Using -beginUpdates/-endUpdates on a cell based tableview may potentially throw an exception "NSTableView Error: Insert/remove/move only works within a -beginUpdates/-endUpdates block." if the cell based table view is layer-backed. This has been fixed for all applications on 10.9 and higher. For prior applications, it is recommended to use a view based NSTableView when using -beginUpdates/-endUpdates, or to not layer-back the table view.

Calling [tableView addTableColumn:] after a call to [tableView moveColumn:toColumn:] may through an exception if done in the same call stack level; this has been fixed in 10.9 for all applications. For applications that need to work around this prior to 10.9, be sure to call -addTableColumn: before calling -moveColumn:toColumn:.

Calling [outlineView removeItemsAtIndexes:inParent:withAnimation:] that results in removing an expanded item may have left the item retained by NSOutlineView for an indefinite amount of time. This has been fixed on 10.9. For applications that need to work around this prior to 10.9, call -collapseItem: before removing the item.

Hiding and unhiding an NSTableColumn (via -setHidden:) will cause the table to automatically resize other table columns to make room for the new table column (or take up slack for the one that was hidden). Previously, this would always attempt to resize columns based on the enclosingScrollView's visible width. On 10.9 this has been changed to prefer the actual width, in the case of a horizontally scrollable table view.

NSTableView has a user default to allow all the default animations it does to be slowed down: NSTableViewSlowMotion YES/NO, which can be set with 'defaults' or a command line parameter.

NSView now exposes a property userInterfaceLayoutDirection, which is backwards available on 10.8 for NSView, and 10.7 for NSOutlineView. userInterfaceLayoutDirection defaults to [NSApp userInterfaceLayoutDirection]. It is up to a particular view's implementation to properly support Right To Left layout. NSOutlineView properly implements the Right To Left layout.

### `NSView` - Layer-backed Views

NSView has some new API to ease layer-backed adoption. The new property canDrawSubviewsIntoLayer allows a parent view to draw all of its subviews into a single layer, when that parent view is layer-backed. This is also sometimes referred to as an “inclusive layer”, as all the children views are drawn inclusively into a single parent layer. Normally, calling -setWantsLayer:YES on a parent view will create individual layers for that parent view and all individual subviews. However, each individual subview will not have wantsLayer=YES, but will inherit its own unique layer by virtue of being in a layer-tree. When canDrawSubviewsIntoLayer is set to YES, the parent view will draw all subviews into a single layer, and each individual subview will not have an individual layer. The exception is a particular subview which already has wantsLayer set to YES on it. It is recommended to first call -setCanDrawSubviewsIntoLayer:YES, and then call -setWantsLayer:YES to avoid unnecessary work. The reason to use canDrawSubviewsIntoLayer=YES, is when there is a view hierarchy which can not be refactored to take advantage of the new Mountain Lion 10.8 API of -wantsUpdateLayer=YES and -updateLayer. Another reason to use this feature is to collapse multiple layers into a single layer, in order to gain better application performance. It is generally recommended to turn canDrawSubviewsIntoLayer on only for parent views which are opaque; otherwise text font-smoothing may not look correct. However, it is acceptable to set canDrawSubviewsIntoLayer to YES for non-opaque views if no text is drawn, or if text is known to draw into some opaque portion of the view (or subview). Note that turning on canDrawSubviewsIntoLayer requires the layerContentsRedrawPolicy to not be NSViewLayerContentsRedrawNever; otherwise subview invalidation will not work. Please note that calling setLayer: with a custom layer will implicitly cause the layerContentsRedrawPolicy to be set to NSViewLayerContentsRedrawNever. This side effect is so AppKit will have a "hands off" approach on custom layers assigned to a view.

Please be aware that using an [NSAnimationContext beginGrouping / endGrouping] will cause a CATransaction to commit; this will cause layer-backed views to potentially get a -viewWillDraw (and a -drawRect: or -updateLayer) immediately after the [NSAnimationContext endGrouping] is called (or [CATransaction commit]).

Layer-backed NSButtons in 10.8 would previously not up-scale the image property, and would not properly use the alternate title when the state changed. Also, when a button was shown with no border (and just a title), the focus ring would not draw. NSButtonCell has been moved to properly use the NSView and NSCell focusRingMask* API. These bugs have been fixed for all applications on 10.9, and any applications providing (or hiding) the focus ring should use the focusRingMask* methods to provide (or customize) the focus ring.

In 10.8 Mountain Lion, layer-backed views would not invalidate the layer if the size was empty (0,0). This has been fixed for applications that link on 10.9 and higher.

Returning [NSNull null] from NSView's -animationForKey: or -defaultAnimationForKey: will now correctly be interpreted as not doing an animation. Previously, it would incorrectly cause the default CALayer animation to happen.

NSSplitView now overrides defaultAnimationForKey: and returns [NSNull null] for the subviews key. This suppresses the subviews animation, which is generally not desired and would be seen as a crossfade.

Layer backed views created by AppKit will now by default have the CALayer edgeAntialiasingMask property set to 0.

There is a new layerContentsRedrawPolicy of NSViewLayerContentsRedrawCrossfade. This can be used to do a crossfade of layer contents when the view's frame size changes. For some views, it also is applicable to views which have contents. For instance, one can easily cross fade the string of an NSTextField with:

	[NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) {
		context.allowsImplicitAnimation = YES;
		textField.stringValue = @"Testing from the treehouse";
	} completionHandler:nil];

Beginning in Mac OS X 10.9 CoreAnimation layer trees are rendered out-of-process. CoreImage filters attached to layers are not supported in this mode. If you are using CoreImage filters on a layer attached to NSView, please set the layerUsesCoreImageFilters property on your view to YES. When set, the layer tree hosting the NSView will be rendered in-process. Failure to set this property will result in an exception being thrown when filters are applied to a layer. Note that if you are setting filters using the NSView properties (backgroundFilters, compositingFilter, or contentsFilters) you do not need to set the layerUsesCoreImageFilters property.

Changes to the lifetime of named NSImages

Prior to Mac OS 10.9 images loaded through +[NSImage imageNamed:] were retained for the lifetime of the application. For applications linked on 10.9 and later this is no longer the case. Images loaded through +[NSImage imageNamed:] will still be cached for a brief time.

Changes to -[NSView allocateGState] and -[NSView releaseGState]

Beginning in Mac OS X 10.9 -[NSView allocateGState] and -[NSView releaseGState] are no ops. These methods were seldom used. Additionally, methods that relied on the side effects of these methods, specifically -[NSView gState] and -[NSWindow gState] will now always return 0. The method -[NSView renewGState] will continue to be invoked as it has in the past, when the view's location in the window has changed.

Changes to the default blend mode for block-based NSImages and NSImageRep subclassers

Beginning in Mac OS X 10.9, NSImage will invoke -[NSImageRep draw] with the current compositing operation set to NSCompositeSourceOver. This matches the behavior of drawing in NSView. Prior to this, -[NSImageRep draw] would be invoked with either the compositing operation passed to NSImage itself, or NSCompositeCopy, depending on the circumstances. If you have subclassed NSImageRep, you may now depend on NSCompositeSourceOver being set when your -draw method is invoked. Likewise, if you are supplying a block to either +[NSImage imageWithSize:flipped:drawingHandler:] or -[NSCustomImageRep initWithSize: flipped:drawingHandler:] you may also depend on NSCompositeSourceOver being the current composite operation when your block is invoked.

Note that if you are deploying to previous OSes (or wish to use a non source-over composite operation) you should explicitly set the drawing operation. This can be done using the -[NSGraphicsContext setCompositeOperation:] API.

Fixes to -layer:shouldInheritContentsScale:fromWindow:

Prior to Mac OS X 10.9, returning YES from a layer delegate's -layer:shouldInheritContentsScale:fromWindow: method would cause AppKit to update the contentsScale property of a CALayer, and then invoke -setNeedsDisplay:YES on the NSView that contained that CALayer. In Mac OS X 10.9, the layer itself will be marked needing display. This fix is conditionalized against apps that have been linked on Mac OS X 10.9 or later.

Reminder about deprecated NSOpenGL functionality

The following NSOpenGL pixel format creation options should be considered deprecated, and have been deprecated by the underlying OpenGL libraries for some time. Their effects should be considered undefined, and their use avoided.

  • NSOpenGLPFAOffScreen
  • NSOpenGLPFAFullScreen
  • NSOpenGLPFASingleRenderer
  • NSOpenGLPFAWindow
  • NSOpenGLPFACompliant
  • NSOpenGLPFAPixelBuffer
  • NSOpenGLPFARemotePixelBuffer
  • NSOpenGLPFARobust
  • NSOpenGLPFAMPSafe
  • NSOpenGLPFAMultiScreen

The OpenGL library option NSOpenGLGOResetLibrary should also be considered deprecated, and its use avoided.

The following methods on NSOpenGLContext should also be considered deprecated. Note that support for these methods no longer exists for many hardware configurations, and their usage may result in crashes.

- (void)setFullScreen;
- (void)setOffScreen:(void *)baseaddr width:(GLsizei)width height:(GLsizei)height rowbytes:(GLint)rowbytes
- (void)copyAttributesFromContext:(NSOpenGLContext *)context withMask:(GLbitfield)mask
- (void)createTexture:(GLenum)target fromView:(NSView *)view internalFormat:(GLenum)format

When trying to create a full-screen context, use a fullscreen NSOpenGLView instead. To render offscreen, please see the documentation regarding OpenGL FrameBufferObjects (FBOs) and glReadPixels.

Finally note that the entirety of the NSOpenGLPixelBuffer class should be considered deprecated. Use IOSurface in conjunction with GL framebuffer objects as a replacement.

NSColor

NSColor now provides three new methods for easier reuse of code that uses UIColor on iOS:

+ (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;

These create colors that are compatible with sRGB. However, where you have a choice, it's better to use the methods such as +colorWithSRGBRed:green:blue:alpha: that specify the color space explicitly.

NSTokenField

There is a UI behavior change introduced for NSTokenField in Mac OS X 10.9. Adjacent Tokens are not longer visually connected when selected. As a dragging source, NSTokenField now removes the tokens drag/dropped with NSDragOperationGeneric (moving the selection).

NSTextField

Setting attributed placeholder string via -setPlaceholderAttributedString: renders the attributed string value while focused.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment