FUIHierarchyView
@MainActor
open class FUIHierarchyView : UIView, FUIContentCopyable
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 FUIHierarchyViewDataSource protocol and set it to hierarchy view’s dataSource property.
class YourHierarchyViewDataSource: FUIHierarchyViewDataSource {}
hierarchyView.dataSource = YourHierarchyViewDataSource()
Register your custom cell if needed. Otherwise hierarchy view will use FUIHierarchyCollectionItem by default.
hierarchyView.register(YourCustomCollectionViewCell.self, forCellWithReuseIdentifier: "ReuseIdentifierForYourCustomCell")
Implement dataSource methods.
// 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 FUIHierarchyViewDelegate protocol and assign it to hierarchy view’s delegate property if needed.
class YourHierarchyViewDelegate: FUIHierarchyViewDelegate {}
hierarchyView.delegate = YourHierarchyViewDelegate()
Theming
Supported class paths:
fdlFUIHierarchyView {}
fdlFUIHierarchyView_header {}
-
The header displayed on the top of hierarchy view. (Only display when horizontalSizeClass equals to compact)
Declaration
Swift
@MainActor public let header: FUIHierarchyViewHeader -
The data source object of hierarchy view.
Declaration
Swift
@MainActor public weak var dataSource: FUIHierarchyViewDataSource? -
The delegate object fo hierarchy view.
Declaration
Swift
@MainActor public weak var delegate: FUIHierarchyViewDelegate? -
A Boolean value that determines whether the hierarchy view is in editing mode.
Declaration
Swift
@MainActor public var isEditing: Bool { get set } -
A Boolean value that determines whether users can select cells while the hierarchy view is in editing mode. By default, only single selection is enable when
allowsSelectionDuringEditingis set true andallowsMultipleSelectionDuringEditingis set to false. Prerequisite:isEditingshould be true.Declaration
Swift
@MainActor public var allowsSelectionDuringEditing: Bool { get set } -
A Boolean value that controls whether users can select more than one cell simultaneously in editing mode. Prerequisite:
isEditingshould be true.Declaration
Swift
@MainActor public var allowsMultipleSelectionDuringEditing: Bool { get set } -
List of UUIDs for selected items.
Declaration
Swift
@MainActor public var selectedUUIDs: [String] { get } -
Register a class for use in creating new collection item cells.
Declaration
Swift
@MainActor open func register(_ cellClass: AnyClass?, forCellWithReuseIdentifier identifier: String)Parameters
cellClassThe class of a cell that you want to use in the hierarchy view.
identifierThe reuse identifier to associate with the specified class. This parameter must not be nil and must not be an empty string.
-
Returns a reusable cell object for an collection item with specified uuid.
Declaration
Swift
@MainActor public func dequeueReusableCell(withReuseIdentifier identifier: String, with uuid: String) -> FUIHierarchyCollectionItemParameters
identifierThe reuse identifier for the specified cell. This parameter must not be nil.
uuidThe uuid of the item which the cell associated with.
Return Value
A
FUIHierarchyViewCollectionItemobject. -
Returns the visible collection item cell for the item with uuid.
Declaration
Swift
@MainActor public func cellForItem(with uuid: String) -> FUIHierarchyCollectionItem?Parameters
uuidThe uuid of the item which the cell associated with.
Return Value
A
FUIHierarchyViewCollectionItemobject ornilif the cell is not visible or uuid does not exists in hierarchy view. -
Reloads all of the data for hierarchy view.
Call this method when you want to reload all the item in hierarchy view. This causes hierarchy view to recalculate the positions and sizes for all items and recreate cells for them. This is an expensive operation so only call this when needed.
Declaration
Swift
@MainActor open func reloadData() -
Insert children located at certain indexes into a parent. The parent must be in expanded state.
Declaration
Swift
@MainActor open func insertChildren(of parent: String, at indexes: IndexSet)Parameters
parentThe parent that gets new children.
indexesThe indexes at which to insert children.
-
Remove children located at specified indexes from a parent. The parent must be in expanded state.
Declaration
Swift
@MainActor open func removeChildren(of parent: String, at indexes: IndexSet)Parameters
parentThe parent from which children are removed.
indexesThe indexes of children that are removed.
-
Invalidate parent of the child specified. The child must be in expanded state.
Call this method when you need to add a new parent(the child has no parent previously), remove the existing parent or replace the parent of an child item. Keep in mind the sibling of the child whose parent gets invalidated will also be removed, you can call
insertChildren(of:at:)to add children of the new parent into the hierarchy view if needed.Declaration
Swift
@MainActor open func invalidateParent(of child: String)Parameters
childThe child whose parent is invalidated.
-
Invalidate children of the parent specified. The parent must be in expanded state.
Call this method when you need to update children of a parent.
Declaration
Swift
@MainActor open func invalidateChildren(of parent: String)Parameters
parentThe parent whose children are invalidated.
-
Invalidate hierarchy items with specified uuids.
Calling this method will ask hierarchy view to reload cells for the items with specified uuids. This method only causes the cells associated with those items to be discarded and redisplay. UUIDs of those items should not change during invalidation.
Declaration
Swift
@MainActor open func invalidateItems(with uuids: [String])Parameters
uuidsThe uuids of hierarchy items who are invalidated.