RSDTaskViewController

open class RSDTaskViewController: UIViewController, RSDTaskController, UIPageViewControllerDelegate, UIPageViewControllerDataSource, RSDAsyncActionControllerDelegate, RSDLoadingViewControllerProtocol

RSDTaskViewController is the default implementation of task view controller that is suitable to the iPhone or iPad. The default implementation will display a series of steps using a UIPageViewController. This controller will also handle starting and stoping async actions and vending the appropriate step view controller for each step.

  • The delegate for the task view controller.

    Precondition

    The delegate must support completion. When the task view controller completes its task, it is the delegate’s responsibility to dismiss it.

    Seealso

    RSDTaskControllerDelegate.taskViewController(:,didFinishWith reason:,error:).

    Declaration

    Swift

    open weak var delegate: RSDTaskViewControllerDelegate?
  • Initializer for initializing using a XIB file.

    Declaration

    Swift

    public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?)

    Parameters

    nibNameOrNil

    The name of the XIB file or nil.

    nibBundleOrNil

    The name of the bundle or nil.

  • Initializer for initializing from a storyboard or restoring from shutdown by the OS.

    Declaration

    Swift

    public required init?(coder aDecoder: NSCoder)

    Parameters

    aDecoder

    The decoder used to create the view controller.

  • Initializer for initializing a view controller that is not associated with a storyboard or nib.

    Declaration

    Swift

    public init(task: RSDTask)

    Parameters

    task

    The task to run using this controller.

  • Initializer for initializing a view controller that is not associated with a storyboard or nib.

    Declaration

    Swift

    public init(taskInfo: RSDTaskInfoStep)

    Parameters

    taskInfo

    The task info (first step) to use to fetch the task to be run using this controller.

  • Main entry for vending an appropriate step view controller for a given step.

    This method will look for a step view controller in the following order:

    1. Call the delegate method taskViewController(:, viewControllerFor step:) and return the view controller supplied by that method. This will throw an exception if the delegate does not return a view controller that conforms to the RSDStepController protocol and inherits from UIViewController.
    2. If the given step implements the RSDStepViewControllerVendor protocol and returns a non-nil instance of a view controller, then that will be returned.
    3. If the given step implements the RSDThemedUIStep protocol and returns a viewTheme, then call instantiateViewController(with viewTheme:) to instantiate a view controller for this step.
    4. If none of the functions listed above returns a view controller then return the view controller instantiated by calling vendDefaultViewController(for step:).

    Declaration

    Swift

    open func viewController(for step: RSDStep) -> (UIViewController & RSDStepController)

    Parameters

    step

    The step to display.

    Return Value

    The view controller to use when displaying a given step.

  • Instantiate a step view controller using the given view theme element.

    Declaration

    Swift

    open func instantiateViewController(with viewTheme: RSDViewThemeElement) -> (UIViewController & RSDStepController)?

    Parameters

    viewTheme

    The view theme element with the nib or storyboard identifier.

    Return Value

    A view controller instantiated with the given view theme element.

  • This is the default factory method for vending a view controller appropriate to a given step. This method is the fall-through for viewController(for step:).

    The view controller vended is a drop-through with the following conditions:

    1. If the step implements the RSDTaskInfoStep protocol then instantiate a RSDTaskInfoStepViewController.
    2. If step.stepType == .countdown then instantiate a RSDCountdownStepViewController.
    3. If the step implements the RSDActiveUIStep protocol, duration > 0, and the step includes the command for RSDActiveUIStepCommand.transitionAutomatically then instantiate a RSDActiveStepViewController.
    4. If RSDTableStepViewController.doesSupport() returns true then instantiate a RSDTableStepViewController
    5. Otherwise, instantiate a DebugStepViewController to be used during development as a placeholder.

    Declaration

    Swift

    open func vendDefaultViewController(for step: RSDStep) -> (UIViewController & RSDStepController)

    Parameters

    step

    The step to display.

    Return Value

    The base class implementation of a step view controller or DebugStepViewController if undefined.

  • Main entry for vending an appropriate async action controller for a given configuration.

    This method will look for an async action controller in the following order:

    1. Call the delegate method taskViewController(:, asyncActionControllerFor configuration:) and return the controller supplied by that method.
    2. If the given configuration implements the RSDAsyncActionControllerVendor protocol and returns a non-nil instance of a controller, then that will be returned.
    3. Otherwise, return the controller instantiated by calling vendDefaultAsyncActionController(for step:).

    Declaration

    Swift

    open func asyncActionController(for configuration: RSDAsyncActionConfiguration) -> RSDAsyncActionController?

    Parameters

    configuration

    The configuration for this async action.

    Return Value

    The async action controller for this confguration, or nil if the action is not supported by this platform.

  • This is the default factory method for vending an async action controller appropriate to a given configuration. This method is the fall-through for asyncActionController(for configuration:).

    The base class will return nil, but this is provided to allow a subclass of RSDTaskViewController to vend an async action controller.

    Declaration

    Swift

    open func vendDefaultAsyncActionController(for configuration: RSDAsyncActionConfiguration) -> RSDAsyncActionController?

    Parameters

    configuration

    The configuration for this async action.

    Return Value

    The async action controller for this confguration, or nil if the action is not supported by this platform.

  • Handle a failure of the async action controller.

    The default implementation will record an error result to the task results and then remove the controller from the list of controllers being managed by the task view controller.

    Declaration

    Swift

    open func asyncActionController(_ controller: RSDAsyncActionController, didFailWith error: Error)

    Parameters

    controller

    The controller that has failed.

    error

    The failure error.

  • Cancel all the async action controllers being managed by this task controller.

    Declaration

    Swift

    public func cancelAllAsyncActions()
  • Optional factory subclass that can be used to vend custom steps that are decoded from a plist or json.

    Declaration

    Swift

    open var factory: RSDFactory?
  • A mutable path object used to track the current state of a running task.

    Declaration

    Swift

    public var taskPath: RSDTaskPath!
  • Can the task progress be saved? This should only return true if the task result can be saved and the current progress can be restored.

    Declaration

    Swift

    open var canSaveTaskProgress: Bool
  • Returns the currently active step controller (if any).

    Declaration

    Swift

    public var currentStepController: RSDStepController?
  • Returns a list of the async action controllers that are currently active. This includes controllers that are requesting permissions, starting, running, and stopping.

    Declaration

    Swift

    public var currentAsyncControllers: [RSDAsyncActionController]
  • Default implementation is to always fetch subtasks.

    Declaration

    Swift

    open func shouldFetchSubtask(for step: RSDTaskInfoStep) -> Bool
  • Default implementation is to always page the section steps.

    Declaration

    Swift

    open func shouldPageSectionSteps(for step: RSDSectionStep) -> Bool
  • Show a loading state while fetching the given task from the task info.

    Declaration

    Swift

    open func showLoading(for taskInfo: RSDTaskInfoStep)

    Parameters

    taskInfo

    The task info for the task being fetched.

  • Fired when the task controller is ready to go forward. This method must invoke the goForward() method either to go forward automatically or else go forward after a user action.

    Declaration

    Swift

    open func handleFinishedLoading()
  • Hide the loading state if currently showing it.

    Declaration

    Swift

    open func hideLoadingIfNeeded()
  • Navigate to the next step from the previous step in the given direction.

    Declaration

    Swift

    public func navigate(to step: RSDStep, from previousStep: RSDStep?, direction: RSDStepDirection, completion: ((Bool) -> Void)?)

    Parameters

    step

    The step to show.

    previousStep

    The previous step. This is either the step currently being displayed or else the RSDSectionStep or RSDTaskStep if the previous step was the last step in a paged section or fetched subtask.

    direction

    The direction in which to show the animation change.

    completion

    The completion to call once the navigation animation has completed.

  • Failed to fetch the task from the current task path. Handle the error. A retry can be fired by calling goForward().

    Declaration

    Swift

    open func handleTaskFailure(with error: Error)

    Parameters

    error

    The error returned by the failed task fetch.

  • The task has completed, either as a result of all the steps being completed or because of an early exit.

    Declaration

    Swift

    open func handleTaskCompleted()
  • This method is called when a task result is ready for upload, save, archive, etc. This method will be called when either (a) the task is ready to dismiss or (b) when the task is displaying the last completion step.

    Declaration

    Swift

    open func handleTaskResultReady(with taskPath: RSDTaskPath)
  • The user has tapped the cancel button.

    Declaration

    Swift

    open func handleTaskCancelled(shouldSave: Bool)

    Parameters

    shouldSave

    Should the task progress be saved (if applicable).

  • Add async action controllers to the shared queue for the given configuations. It is up to the task controller to decide how to create the controllers and how to manage adding them to the currentStepController array.

    The async actions should not be started. Instead they should be returned with idle status.

    Note

    If creating the recorder might take time, the task controller should move creation to a background thread so that the main thread is not blocked.

    Declaration

    Swift

    public func addAsyncActions(with configurations: [RSDAsyncActionConfiguration], completion: @escaping (([RSDAsyncActionController]) -> Void))

    Parameters

    configurations

    The configurations to start.

    completion

    The completion to call with the instantiated controllers.

  • Start the async action controllers. The protocol extension calls this method when an async action should be started directly after the step is presented.

    The task controller needs to handle blocking any navigation changes until the async controllers are ready to proceed. Otherwise, the modal popup alert can be swallowed by the step change.

    Declaration

    Swift

    public func startAsyncActions(for controllers: [RSDAsyncActionController], showLoading: Bool, completion: @escaping (() -> Void))
  • Stop the async action controllers. The protocol extension does not directly implement stopping the async actions to allow customization of how the results are added to the task and whether or not forward navigation should be blocked until the completion handler is called. When the stop action is called, the view controller needs to handle stopping the controllers, adding the results, and showing a loading state until ready to move forward in the task navigation.

    Declaration

    Swift

    public func stopAsyncActions(for controllers: [RSDAsyncActionController], showLoading: Bool, completion: @escaping (() -> Void))
  • The page view controller used to control the view controller navigation.

    Declaration

    Swift

    public private(set) var pageViewController: (UIViewController & RSDPageViewControllerProtocol)!
  • Convenience method for casting the current step controller to a UIViewController.

    Declaration

    Swift

    open var currentStepViewController: (UIViewController & RSDStepController)?
  • This is a work-around to not being able to hook up child view controllers via the storyboard IBOutlet. The method is called in viewDidLoad to see if there is already a view controller of the expected type that is included in the storyboard or nib that was used to create this view controller.

    Declaration

    Swift

    open func findPageViewController() -> (UIViewController & RSDPageViewControllerProtocol)?

    Return Value

    If found, returns a view controller that conforms to RSDPageViewControllerProtocol.

  • This method will add a page view controller in the instance where this view controller was loaded without one. The method is called in viewDidLoad if findPageViewController returns nil. This method should instantiate a view controller and add it to this view controller as a child view controller.

    Declaration

    Swift

    open func addPageViewController() -> (UIViewController & RSDPageViewControllerProtocol)

    Return Value

    A view controller that conforms to RSDPageViewControllerProtocol.

  • Override viewDidLoad() to set up the page view controller.

    Declaration

    Swift

    open override func viewDidLoad()
  • Override viewWillAppear() to start the task if needed.

    Declaration

    Swift

    open override func viewWillAppear(_ animated: Bool)
  • Respond to a gesture to go back. Always returns nil but will call goBack() if appropriate.

    Declaration

    Swift

    open func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController?
  • Respond to a gesture to go forward. Always returns nil but will call goForward() if appropriate.

    Declaration

    Swift

    open func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController?
  • The audio session is a shared pointer to the current audio session (if running). This is used to allow background audio. Background audio is required in order for an active step to play sound such as voice commands to a participant who make not be looking at their screen.

    For example, a Walk and Balance task that measures gait and balance by having the participant walk back and forth followed by having them turn in a circle would require turning on background audio in order to play spoken instructions even if the screen is locked before putting the phone in the participant’s pocket.

    Note

    The application settings will need to include setting capabilities appropriate for background audio if this feature is used.

    Declaration

    Swift

    public private(set) var audioSession: AVAudioSession?
  • Start the background audio session if needed. This will look to see if audioSession is already started and if not, will start a new session.

    Declaration

    Swift

    public func startBackgroundAudioSessionIfNeeded()