Class

NSPage​Controller

The NSPage​Controller class is used for controlling swipe navigation and animations between views or view content. It is useful for user interfaces which control navigating multiple pages as in a book or a web browser history.

Overview

Page controller inherits from the NSView​Controller class . You must assign the view property to a view in your view hierarchy. The NSPage​Controller class does not vend a view. The NSPageController class does insert itself into the responder chain.

Conceptually, the page controller manages swiping between an array of pages, the arranged​Objects. Using the selected​Index property, you can determine how many pages forward or backward the user may navigate.

Page Controller Modes

There are two modes that an NSPage​Controller instance may operate in, history mode and book mode. The main difference between the two modes is that History mode expects page​Controller.view to be the content and Book mode expects page​Controller.view to be be a container for the content that you will supply by returning view​Controllers in your delegate methods.

History Mode

History mode is designed to be the easiest way to create a history user interface. The page controller will manage the history (the arranged​Objects property), snapshots, and user navigation between pages in the history.

As the user navigates to new content, add to the history by calling navigate​Forward(to:​). The page controller will remove any arranged​Objects after the selected​Index and then add the object to the end of the arranged​Objects array and update the selected​Index property. Just like navigating in a new direction in a web browser, all forward history is lost once the user starts navigating a new path. After returning from navigate​Forward​To​Object:​ you are free to update the contents of page​Controller.view.

Delegate Method Invocation During History Mode Swiping

During swiping, the following optional delegate methods are called in the specified order:

The page​Controller​Will​Start​Live​Transition(_:​) delegate method is invoked when the user starts a swipe action. This is the appropriate point at which to save information that you may need to restore, such as a page’s scrolled location.

Upon returning from the this delegate method, page​Controller.view is hidden. In it's place the page controller shows a private view hierarchy to animate previously taken snapshots of the page history. This allows the page controller to remain responsive to the user without any required action by your application. Next, if implemented, the page​Controller(_:​did​Transition​To:​) delegate method is invoked. This delegate method is called after a physically successful swipe, but before the animation has completed. The supplied object is the page the user navigated to – the new selected​Index object in arranged​Objects. If background loading tasks need to be initiated this is the appropriate time to do so. However, do not block the main thread or the animation will stutter or pause.

Finally, the pageControllerDidEndLiveTransition: delegate method is invoked after the swipe and swipe animations are complete. You should any position settings or other display specific state stored in the page​Controller​Will​Start​Live​Transition(_:​) implementation. The page​Controller.view is still hidden at this point and you must call complete​Transition() on the page controller instance to inform the instance to hide the private transition view and show page​Controller.view. Often you do this immediately, however, if your content is not ready you can call this at a later.

Book Mode (View Controller Mode)

Book mode is designed to give you more control over the swiping process and to facilitate more user interface designs than just history, although you can use book mode to create a history user interface.

In this mode, page​Controller.view is a container view and the content views are vended by view controller instances supplied by the delegate object.

To enable book mode, you must implement the following two methods in your delegate: page​Controller(_:​identifier​For:​) and page​Controller(_:​view​Controller​For​Identifier:​).

The page controller instance caches the view controllers supplied for each identifier and only asks it's delegate to create more if one does not already exists in its cache. If you have different type of views you want to swipe in, then supply a different identifier for each type.

When needed, you will be asked to prepare a view controller instance with a page via the optional delegate method page​Controller(_:​prepare:​with:​). If you do not implement this method, then the represented​Object of the view controller that would have been passed to this delegate method is set as the object.

The delegate will be asked to prepare a view controller with a nil object for each unique identifier it encounters. The NSPageController instance will use this to generate a default snapshot for that identifier.

When using the book mode, if page​Controller.view is layer backed, live layers are used during transition instead of snapshots.

Generally, when using book mode, the set of pages are known and it is your responsibility to set the arranged​Objects array property and initially selected page using the selected​Index property.

Delegate Method Invocation During Book Mode Swiping

During swiping, the following optional delegate methods are called in the specified order:

The delegate method page​Controller​Will​Start​Live​Transition(_:​) is invoked when the user starts a swipe action. As in history mode, this is the appropriate point at which to save information that you may need to restore, such as a page’s scrolled location.

After returning from the page​Controller​Will​Start​Live​Transition(_:​) delegate method, the page controller takes a snapshot of the view in the specified selected​View​Controller and then removes it from page​Controller.view. The page controller replaces it with a private view hierarchy to animate previously taken snapshots. Unlike when building up a history, snapshots may not yet exist for the page being navigated to. In this case, a previously gathered default snapshot is used for that page's identifier. Regardless, if using a default snapshot or a previously gathered snapshot of actual contents, a view controller is prepared for the page being navigated to, and passed to the delegate. This view​Controller.view is then asked to draw on a background thread while swiping continues. Note that at this point the view does not reside within a window. Once the background threaded drawing completes, the initial snapshot is replaced with the newly generated snapshot.

Next the page​Controller(_:​did​Transition​To:​) delegate method is invoked after a physically successful swipe, but before the animation has completed. The supplied object is the page the user navigated to - the new object in the arranged​Objects array at the selected​Index. Note that the page controller’s selected​View​Controller has not been updated yet. If you need to start some background loading tasks, now is the time to do it. Do not block the main thread or the animation will stutter or pause.

Finally the page​Controller​Did​End​Live​Transition(_:​) method is invoked after the swipe and swipe animations are complete. The selected​View​Controller.view is still detached at this point and you must call complete​Transition() on the page controller to hide the private transition view and update the selected​View​Controller. Often you do this immediately, however, if your content is not ready you can call this at a later.

Completing the Page Controller Transition

An NSPage​Controller instance uses a private view hierarchy during swiping. To create a seamless transition to the new content, it is your responsibility to inform the page controller when you are ready to draw the new content. Ideally, the new content should match the snapshot so the user is none the wiser. You inform the page controller to complete the transition by calling complete​Transition(). If needed, a view controller is prepared and then the content view is shown (or added) to the view hierarchy and the private transition view is hidden.

During page controller initiated animations, page​Controller​Will​Start​Live​Transition(_:​) and page​Controller​Did​End​Live​Transition(_:​) are invoked on the delegate. Generally during page​Controller​Did​End​Live​Transition(_:​) you will call complete​Transition(). Programatic animations via the animator proxy do not call the delegate methods and you are responsible for calling complete​Transition() when the animation completes.This is easily done via a completion handler on an NSAnimation​Context grouping. For example:

 //To instantly change the selectedIndex:
  pageController.selectedIndex = newIndex;
 
  //To animate a selectedIndex change:
  [NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) {
    [[pageController animator] setSelectedIndex:newIndex];
  } completionHandler:^{
    [pageController completeTransition];
  }];

Symbols

Page Controller Items

var arranged​Objects:​ [Any]

An array containing the objects displayed in the page controller’s view.

func navigate​Forward(to:​ Any)

Navigates to the specific object.

var selected​Index:​ Int

The currently selected object in the arranged objects array.

Page Controller Navigation

func navigate​Back(Any?)

Navigates backwards in the page controller’s arranged objects array.

func navigate​Forward(Any?)

Navigates to the next object in the page controller’s arranged objects array, if appropriate.

func take​Selected​Index​From(Any?)

Navigates to the selected index, which is taken from the sender.

Getting and Setting the Delegate

var delegate:​ NSPage​Controller​Delegate?

The page controller’s delegate object.

Transition Style

var transition​Style:​ NSPage​Controller​Transition​Style

The transition style the page controller uses when changing pages.

Completing Page Transition

func complete​Transition()

Invoked when the page transition is completed.

Getting the View Controller

var selected​View​Controller:​ NSView​Controller?

The view controller associated with the selected object..

Constants

NSPage​Controller​Transition​Style

These constants control the transition style of the page controller.