Hierarchy View
-
A view controller which specializes in managing a hierarchy view. When
FUIHierarchyViewControllerinitiates, it sets data source and delegate of hierarchy view to self.Components
hierarchyView
Usage
Subclass
FUIHierarchyViewControllerwhen you need to show a hierarchy view. It conforms toFUIHierarchyViewDataSourceandFUIHierarchyViewDelegateby default.class MyController: FUIHierarchyViewController {}Override
viewDidLoadand do some setup here. You should register your custom cell if needed. Otherwise hierarchy view will useFUIHierarchyCollectionItemby default.override func viewDidLoad() { super.viewDidLoad() hierarchyView.register(YourCustomCollectionViewCell.self, forCellWithReuseIdentifier: "ReuseIdentifierForYourCustomCell") // do more setup here. }Implement
dataSourceand delegate methods// Define your data model. var model = HierarchyViewModel() override func rootUUID(in hierarchyView: FUIHierarchyView) -> String? { return model.rootObject?.uuid } override func hierarchyView(_ hierarchyView: FUIHierarchyView, numberOfChildrenForItemWith uuid: String) -> Int { guard let object = model.getObject(for: uuid) else { preconditionFailure("Object with String: \(uuid) does not exsit in model") } if let children = object.children { return children.count } // Get children asynchronously if they haven't been loaded yet. When loading completes, cache those children for future access and insert children into hierarchy view by calling `insertChildren(of:at:)`. object.asyncFetchChildren { children in self.model.updateCache(objects: children) self.hierarchyView.insertChildren(of: uuid, at: IndexSet(integersIn: 0..<children.count)) } // Return zero children before children is loaded. return 0 } override func hierarchyView(_ hierarchyView: FUIHierarchyView, uuidForChildItemAt index: Int, with parentUUID: String) -> String { guard let parent = model.getObject(for: parentUUID) else { preconditionFailure("Parent object with String: \(parentUUID) does not exsit") } guard let children = parent.children else { preconditionFailure("Children of parent: \(parent) is not loaded yet") } return children[index].uuid } override func hierarchyView(_ hierarchyView: FUIHierarchyView, parentForItemWith uuid: String) -> String? { guard let object = model.getObject(for: uuid) else { preconditionFailure("Object with String: \(uuid) does not exsit in model") } if let parent = object.parent { return parent.uuid } // Get parent asynchronously if they haven't been loaded yet. When loading completes, cache the parent for future access and insert it into hierarchy view by calling `invalidateParent(of:)`. object.asyncFetchParent { parent in guard let parent = parent else { return } self.model.updateCache(objects: [parent]) self.model.updateRootObject(newRootObject: parent) self.hierarchyView.invalidateParent(of: uuid) } // Return nil before parent is loaded. return nil } override func hierarchyView(_ hierarchyView: FUIHierarchyView, cellForItemWith uuid: String) -> FUIHierarchyCollectionItem { let cell = hierarchyView.dequeueReusableCell(withReuseIdentifier: “ReuseIdentifierForYourCustomCell”, with: uuid) as! YourCustomCollectionViewCell guard let object = model.getObject(for: uuid) else { return cell } cell.title.text = object.name cell.subtitle.text = object.type cell.body.text = object.location cell.accessoryType = .disclosureIndicator if object.numberOfChildren > 0 { cell.isHierarchyButtonHidden = false cell.hierarchyAttributeText = String(object.numberOfChildren) } else { cell.isHierarchyButtonHidden = true } return cell } override func hierarchyView(_ hierarchyView: FUIHierarchyView, titleForItemWith uuid: String) -> String? { return model.getObject(for: uuid)?.name }Theming
Supported class paths:
See morefdlHierarchyViewController_hierarchyView {}Declaration
Swift
@MainActor open class FUIHierarchyViewController : UIViewController, FUIHierarchyViewDataSource, FUIHierarchyViewDelegate -
A view that manages a collection of items in a multi-column layout.
Initial Loading Process:
- Hierarchy view asks data source for a root item and put it in the first column. Hierarchy view will be empty if
nilis returned for root. If so, hierarchy view finishes loading. - Hierarchy view asks data source for number of children of the root and get each child item iteratively.
- Hierarchy view asks data source for the parent of root item. If that parent exists, insert it into preview column before the root.

Interaction Behavior:
Expand Children
Tap on the hierarchy accessory view will drill down one level in the hierarchy view to show the children of tapped item.


Swipe
Quick swipe left/right to view the previous or next level in the hierarchy.


Pan
Pan left/right to navigate further in hierarchy view.

Usage
Have your data source object conform to
FUIHierarchyViewDataSourceprotocol and set it to hierarchy view’sdataSourceproperty.class YourHierarchyViewDataSource: FUIHierarchyViewDataSource {} hierarchyView.dataSource = YourHierarchyViewDataSource()Register your custom cell if needed. Otherwise hierarchy view will use
FUIHierarchyCollectionItemby default.hierarchyView.register(YourCustomCollectionViewCell.self, forCellWithReuseIdentifier: "ReuseIdentifierForYourCustomCell")Implement
dataSourcemethods.// Define your data model. var model = HierarchyViewModel() func rootUUID(in hierarchyView: FUIHierarchyView) -> String? { return model.rootObject?.uuid } func hierarchyView(_ hierarchyView: FUIHierarchyView, numberOfChildrenForItemWith uuid: String) -> Int { guard let object = model.getObject(for: uuid) else { preconditionFailure("Object with String: \(uuid) does not exsit in model") } if let children = object.children { return children.count } // Get children asynchroniously if they haven't been loaded yet. When loading completes, cache those children for future access and insert children into hierarchy view by calling `insertChildren(of:at:)`. object.asyncFetchChildren { children in self.model.updateCache(objects: children) self.hierarchyView.insertChildren(of: uuid, at: IndexSet(integersIn: 0..<children.count)) } // Return zero children before children is loaded. return 0 } func hierarchyView(_ hierarchyView: FUIHierarchyView, uuidForChildItemAt index: Int, with parentUUID: String) -> String { guard let parent = model.getObject(for: parentUUID) else { preconditionFailure("Parent object with String: \(parentUUID) does not exsit") } guard let children = parent.children else { preconditionFailure("Children of parent: \(parent) is not loaded yet") } return children[index].uuid } func hierarchyView(_ hierarchyView: FUIHierarchyView, parentForItemWith uuid: String) -> String? { guard let object = model.getObject(for: uuid) else { preconditionFailure("Object with String: \(uuid) does not exsit in model") } if let parent = object.parent { return parent.uuid } // Get parent asynchronously if they haven't been loaded yet. When loading completes, cache the parent for future access and insert it into hierarchy view by calling `invalidateParent(of:)`. object.asyncFetchParent { parent in guard let parent = parent else { return } self.model.updateCache(objects: [parent]) self.model.updateRootObject(newRootObject: parent) self.hierarchyView.invalidateParent(of: uuid) } // Return nil before parent is loaded. return nil } func hierarchyView(_ hierarchyView: FUIHierarchyView, cellForItemWith uuid: String) -> FUIHierarchyCollectionItem { let cell = hierarchyView.dequeueReusableCell(withReuseIdentifier: “ReuseIdentifierForYourCustomCell”, with: uuid) as! YourCustomCollectionViewCell guard let object = model.getObject(for: uuid) else { return cell } cell.title.text = object.name cell.subtitle.text = object.type cell.body.text = object.location cell.accessoryType = .disclosureIndicator if object.numberOfChildren > 0 { cell.isHierarchyButtonHidden = false cell.hierarchyAttributeText = String(object.numberOfChildren) } else { cell.isHierarchyButtonHidden = true } return cell } func hierarchyView(_ hierarchyView: FUIHierarchyView, titleForItemWith uuid: String) -> String? { return model.getObject(for: uuid)?.name }Make your delegate object conform to
FUIHierarchyViewDelegateprotocol and assign it to hierarchy view’s delegate property if needed.class YourHierarchyViewDelegate: FUIHierarchyViewDelegate {} hierarchyView.delegate = YourHierarchyViewDelegate()Theming
Supported class paths:
See morefdlFUIHierarchyView {} fdlFUIHierarchyView_header {}Declaration
Swift
@MainActor open class FUIHierarchyView : UIView, FUIContentCopyable - Hierarchy view asks data source for a root item and put it in the first column. Hierarchy view will be empty if
-
A concrete layout class that manages the layout of hierarchy view.
This layout organizes items into different columns from left to right (right to left if in opposite layout direction) where items in one column happens to be the children of expanded item in the previous column. This layout is specially designed for hierarchy view so it is supposed to be used along with hierarchy view.
See moreDeclaration
Swift
@MainActor open class FUIHierarchyCollectionViewLayout : UICollectionViewLayout, UIScrollViewDelegate -
The FUIHierarchyViewDelegate protocol defines methods that allow you to manage the selection of items or tapping on hierarchy accessory view of collection item cell in a hierarchy view. The methods of this protocol are all optional.
See moreDeclaration
Swift
@objc public protocol FUIHierarchyViewDelegate -
An object that adopts the UICollectionViewDataSource protocol is responsible for providing the data required by a hierarchy view. It also handles the creation and configuration of cells used by the hierarchy view to display your data.
See moreDeclaration
Swift
public protocol FUIHierarchyViewDataSource : AnyObject -
FUIHierarchyItemTableViewCellis a table view UI component which extendsFUIObjectBaseTableViewCellfor showing a collection item’s business object content and hierarchy information (e.g. number of children in its next level). It is identical toFUIHierarchyCollectionItemin terms of the configuration of inner view and hierarchy indicator.Initialization and Configuration:
To use
FUIHierarchyItemTableViewCell, it should be dequeued fromhierarchyViewand returned in the data source method inFUIHierarchyViewDataSource.Example of setting an
FUIHierarchyCollectionItemin a table view:cell.title.text = "Business Object Title" cell.subtitle.text = "Business Object Subtitle" cell.footnote.text = "Business Object Footnote" cell.hierarchyIndicator.title.text = "128" cell.status.text = "Business Object Status" cell.accessoryType = .disclosureIndicatorSettings of Hierarchy Indicator:
Similar to
FUIHierarchyCollectionItem, hierarchy indicator is used to display related hierarchy information. To customize a different text in hierarchy indicator, set thetextfortitleproperty of the cell’sFUIHierarchyIndicator.cell.hierarchyIndicator.title.text = "My Title"Likewise, hierarchy indicator by default is displayed in a vertical aligned multi-line mode in
FUIHierarchyCollectionItem. To display in single-line mode, configure theisMultilineproperty of the cell’sFUIHierarchyIndicator.cell.hierarchyIndicator.isMultiline = falseLayout of Hierarchy Indicator in Table View:
The default width of the space showing hierarchy indicator is
38pxin multi-line mode and74pxin multi-line mode. So the table view controller consuming theFUIHierarchyItemTableViewCellshould enforce this minimum layout margin based on its display mode. The recommended technique for managing this is to set the table view controller’sadditionalSafeAreaInsetsproperty accordingly.override func viewDidLoad() { self.tableView.showsVerticalScrollIndicator = false self.tableView.insetsContentViewsToSafeArea = false if UIView.userInterfaceLayoutDirection(for: self.view.semanticContentAttribute) == .leftToRight { self.additionalSafeAreaInsets.right = 38 } else { self.additionalSafeAreaInsets.left = 38 } }Default Styling:
Depending on the selection state, the tint color and button style of hierarchy icon, the font size of the title text, and the cell’s background color will be updated automatically.
Customize Selection Behavior:
Similar to
FUIHierarchyCollectionItem, selection behavior can be customized by conforming toFUIHierarchyViewDelegateand then implementing thehierarchyButtonTappedForItemWithmethod.AccessoryView,AccessoryType, andEditingAccessoryViewStandard
UITableViewCellproperties likeaccessoryView,accessoryType, andeditingAccessoryVieware supported.Theming
Supported class paths:
fdlFUIBaseCollectionViewCell {} fdlFUIBaseCollectionViewCell_title {} fdlFUIBaseCollectionViewCell_subtitle {} fdlFUIBaseCollectionViewCell_footnote {} fdlFUIBaseCollectionViewCell_detailImageView {}Please refer to
See moreFUIHierarchyItemViewandFUIHierarchyIndicatordocumentation for all supported attributes.Declaration
Swift
@MainActor open class FUIHierarchyItemTableViewCell : FUIObjectBaseTableViewCell<FUIHierarchyItemView> -
A header view sits at top of hierarchy view. Header label displays the title of the selected parent item in previous section. You can use left/right button to navigate back or forth in the hierarchy.
Theming
Supported class paths:
fdlFUIHierarchyViewHeader {} fdlFUIHierarchyViewHeader_title {} fdlFUIHierarchyViewHeader_leftButton {} fdlFUIHierarchyViewHeader_rightButton {}Please refer to
See moreFUIButtondocumentation for all supported attributes.Declaration
Swift
@MainActor open class FUIHierarchyViewHeader : UIView, FUIViewBorderDrawing -
Base inner view showing business object information for
FUIHierarchyItemTableViewCellandFUIHierarchyCollectionItem.Example Initialization and Configuration:
let view = FUIHierarchyItemView() view.title.text = "Business Object Title" view.subtitle.text = "Business Object Subtitle" view.footnote.text = "Business Object Footnote" view.status.text = "Business Object Status" view.statusImageView.image = UIImage(named: <#image#>) view.iconImages = ["1", FUIIconLibrary.indicator.veryHighPriority.withRenderingMode(.alwaysTemplate)]Theming
Supported
TEXTclass paths:fdlFUIHierarchyItemView_title {} fdlFUIHierarchyItemView_subtitle {} fdlFUIHierarchyItemView_footnote {} fdlFUIHierarchyItemView_status {}Supported
TEXTproperties:font-color: Color; font-style: UIFontTextStyle; text-align: NSTextAlignment;Supported
IMAGEclass paths:fdlFUIHierarchyItemView_detailImageView {}Supported
IMAGEproperties:
See moretint-color: Color;Declaration
Swift
@MainActor open class FUIHierarchyItemView : FUIObjectViewBase, FUIHierarchyItemComponent -
FUIHierarchyCollectionItemis a collection view UI component which extendsFUITableViewAccessoryDrawingCollectionViewCellfor showing a collection item’s business object content and hierarchy information (e.g. number of children in its next level). It is the default cell for displaying hierarchy items in anFUIHierarchyView.Initialization and Configuration:
To use
FUIHierarchyCollectionItem, it should be dequeued fromhierarchyViewand returned in the data source method inFUIHierarchyViewDataSource.Example of setting an
FUIHierarchyCollectionItemby implementingcellForItemWithin the hierarchy view:cell.title.text = "Business Object Title" cell.subtitle.text = "Business Object Subtitle" cell.footnote.text = "Business Object Footnote" cell.accessoryType = .disclosureIndicator cell.statusImage = FUIIconLibrary.indicator.veryHighPriority cell.hierarchyIndicator.title.text = "999,999"Hierarchy Indicator:
Hierarchy indicator provides a stacked view which includes two components: a text view, and a hierarchy icon. In hierarchy view, the text view is used to show the number of children belongs to the specific hierarchy item. Once the hierarchy indicator is tapped, the hierarchy view will be expanded to display a list of its children in a new column. The icon indicates that if the hierarchy item has been expanded or not. To customize a different text in hierarchy indicator, set the
textfortitleproperty of the cell’sFUIHierarchyIndicator.cell.hierarchyIndicator.title.text = "My Title"Hierarchy indicator has two ways to layout its components: multi-line mode and single-line mode. By default, it is displayed in a vertical aligned multi-line mode. To horizontally align its components in a single-line mode, configure the
isMultilineproperty of the cell’sFUIHierarchyIndicator.cell.hierarchyIndicator.isMultiline = falseDefault Styling:
Depending on the selection state, the tint color and button style of hierarchy icon, the font size of the title text, and the cell’s background color will be updated automatically.
Customize Selection Behavior:
By default after selection the hierarchy item cell will be expanded. Selection behavior can be customized by conforming to
FUIHierarchyViewDelegateand then implementing thehierarchyButtonTappedForItemWithmethod. To support additional gesture handling, a developer would usually add a gesture recognizer. This can be added directly to the cell when it is being dequeued, or added to collection view containing the cell.In the following example, a long press gesture recognizer is added to each hierarchy collection cell:
let longPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(didLongPress(_:))) longPressGestureRecognizer.minimumPressDuration = 0.5 cell.addGestureRecognizer(longPressGestureRecognizer)Theming:
Supported class paths:
fdlFUIHierarchyCollectionItem {}Please refer to
See moreFUIHierarchyItemViewandFUIHierarchyIndicatordocumentation for all supported attributes.Declaration
Swift
@MainActor open class FUIHierarchyCollectionItem : FUITableViewAccessoryDrawingCollectionViewCell<FUIHierarchyItemView>, InnerViewContainerEventHandling, FUIContentCopyable -
See moreFUIHierarchyStateis an hierarchy object that defines its selection state: normal or selected.Declaration
Swift
public struct FUIHierarchyState : Hashableextension FUIHierarchyState: Enableableextension FUIHierarchyState: Defaultable
-
Hierarchy indicator is a stack view including a hierarchy icon and the specific item’s hierarchy title text view, which is used by
FUIHierarchyItemTableViewCellandFUIHierarchyCollectionItem.Theming
Supported class paths:
fdlFUIHierarchyIndicator_title {}
Supported
TEXTproperties:font-color: Color; font-style: UIFontTextStyle; text-align: NSTextAlignment;
See moreDeclaration
Swift
@MainActor open class FUIHierarchyIndicator : FUITintableDrawingView<FUIHierarchyState>, FUITitleComponent