Skip to content

UX SDK Hooks

Cristina Suciu edited this page Dec 23, 2020 · 1 revision

UX SDK 5 has been written to allow developers to use UX SDK widgets, write their own widgets, or modify and extend the widgets supplied in UX SDK 5. Widgets can be customized to match a developers application appearance and color scheme.

Hooks and What They Are

In addition to the flexibility provided, UX SDK also provides a new feature called Hooks for receiving event and widget status changes without having to write or override existing widgets. These hooks are sent to listeners who register for them whenever a hook event happens.

Hooks allow your application a consistent way to handle respond to changes without implementing detailed code to access and monitor underlying states. If you are collecting analytics information on certain areas hooks can also supply those changes for recording.

General hook format and data containment

Hooks consist of the following parts: a sender, a receiver object, and the hook object with data itself. Hooks are defined as a key and one or more pieces of data containing relevant information, packaged into an instance of a hook class.

On iOS each hook is sent as an object descended from DUXBetaStateChangeBaseData. See below for details on unpacking the hook object data. When listening for a hook, if you have a common listener, you can examine the hook object using either isKindOfClass: for a specific sender, or isMemberOfClass: to check the senders class hierarchy, and inspect the key to know what type of value to extract from the hook. In Swift, you can use downcasting to test for memebership in a heirachy using as?, downcasting to a specific class or the relevent class superclass.

Standard Hook Class Naming Conventions

There are two standard naming conventions for hook classes: UIState and ModelState. may not always be exact name of the class due to some classes having very long names which (such as the System Status List Item classes.) For example, the classes DUXBetaMaxAltitudeListItemWidget and DUXBetaMaxAltitudeListItemWidgetModel have their hook names shortened to MaxAltitudeItemUIState and MaxAltitudeItemModelState, dropping the DUXBeta prefix and ListItem from both in the interests of convenience.

UIState hook classes refer to the actual display widget and changes made in the user interface by the user. ModelState hook classes are used to send information about the underlying model used by the widget. The widget model is gnerally responsible for interacting with the aircraft settings and has no direct user interface.

Inside each of these classes, the standard hook naming convention is to define the hook as a past tense verb state, such as productConnected or maxAltitudeChanged and then including the appropriate information in the hook object.

How to receive only the hooks you want

The class DUXBetaStateChangeBroadcaster supplies a singleton for distribution of hooks. To register to receive the hooks of a particular class:

Swift

DUXBetaStateChangeBroadcaster.instance().registerListener(self, analyticsClassName: @“VisionModelState”) { [weak self] (analyticsData) in
    if analyticsData.key() == “visionSystemStatusUpdated{
        // Your Interesting Code Goes Here
    }
}

Objective-C

[[DUXBetaStateChangeBroadcaster instance] registerListener:self analyticsClassName:@“VisionModelState” handler:^(DUXBetaStateChangeBaseData *analyticsData) {
    if ([[analyticsData key] isEqualToString:@“visionSystemStatusUpdated”]) {
        // Your Interesting Code Goes Here
    }
}];

Each of these example shows using a single block/closure to handle each class of hook, a common block can be written and passed to each registration call, letting you encapsulate all hook handling into a single block.

The developer can stop listening for an individual hook class by calling unregisterListener:forClassName on the DUXBetaStateChangeBroadcaster instance, or can remove all listeners registered to an object by calling unregisterListner:.

Unpacking Hooks

The DUXBetaStateChangeBaseData class supplies the following accessors for contained data extraction:

- (NSString*)key;
- (NSValue*)value;
- (NSNumber*)number;
- (NSString*)string;
- (id)object;

The documentation for each hook describes what type of data is sent. The appropriate method should be called to extract the value from the hook.

Hooks passing boolean values always pass then as NSNumbers. 0 is false, 1 is true, as usual.

Hook Example

An example of using a hook to monitor for UI changes or interaction and then performaing an action based on that information can be found in the DefaultLayoutViewController to show the SystemStatusListPanel when the DUXBetaSystemStatusWidget is tapped.

Here a listener is installed for the DUXBetaSystemStatusUIState which is sent by the DUXBetaSystemStatusWidget. When a hook from that class is received, the key is inspected to determine if it was a widgetTapped event and the systemStatusListPanel is then shown or closed as appopriate.

Swift

DUXBetaStateChangeBroadcaster.instance().registerListener(self, analyticsClassName: "DUXBetaSystemStatusUIState") { [weak self] (analyticsData) in
    DispatchQueue.main.async {
        if let weakSelf = self {
            if analyticsData.key() != "widgetTapped" {
                return
            }
            if let list = weakSelf.systemStatusListPanel {
                list.closeTapped()
                weakSelf.systemStatusListPanel = nil
            } else {
                weakSelf.setupSystemStatusList()
            }
        }
    }
}

Objective-C

__weak DefaultLayoutViewController *weakSelf = self;
[[DUXBetaStateChangeBroadcaster instance] registerListener:self analyticsClassName:@"DUXBetaSystemStatusUIState" handler:^(DUXBetaStateChangeBaseData *analyticsData) {
    dispatch_async(dispatch_get_main_queue(), ^(void) {
        __strong DefaultLayoutViewController *strongSelf = weakSelf;
        if ([[analyticsData key] isEqualToString:@"widgetTapped"] == NO) {
                return;
            }
            if (strongSelf.systemStatusListPanel) {
                [strongSelf closeTapped];
                strongSelf.systemStatusListPanel = nil;
            } else {
                [strongSelf setupSystemStatusList];
            }
        }
    }
}

Notes

  1. All widgets with widget models will provide Model Hooks.
  2. Only the widgets which have significant UI changes or interactions will provide UI Hooks.
Clone this wiki locally