FUIHierarchyView
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
nil
is 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
public let header: FUIHierarchyViewHeader
-
The data source object of hierarchy view.
Declaration
Swift
public weak var dataSource: FUIHierarchyViewDataSource?
-
The delegate object fo hierarchy view.
Declaration
Swift
public weak var delegate: FUIHierarchyViewDelegate?
-
A Boolean value that determines whether the hierarchy view is in editing mode.
Declaration
Swift
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
allowsSelectionDuringEditing
is set true andallowsMultipleSelectionDuringEditing
is set to false. Prerequisite:isEditing
should be true.Declaration
Swift
public var allowsSelectionDuringEditing: Bool { get set }
-
A Boolean value that controls whether users can select more than one cell simultaneously in editing mode. Prerequisite:
isEditing
should be true.Declaration
Swift
public var allowsMultipleSelectionDuringEditing: Bool { get set }
-
List of UUIDs for selected items.
Declaration
Swift
public var selectedUUIDs: [String] { get }
-
Register a class for use in creating new collection item cells.
Declaration
Swift
open func register(_ cellClass: AnyClass?, forCellWithReuseIdentifier identifier: String)
Parameters
cellClass
The class of a cell that you want to use in the hierarchy view.
identifier
The 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
public func dequeueReusableCell(withReuseIdentifier identifier: String, with uuid: String) -> FUIHierarchyCollectionItem
Parameters
identifier
The reuse identifier for the specified cell. This parameter must not be nil.
uuid
The uuid of the item which the cell associated with.
Return Value
A
FUIHierarchyViewCollectionItem
object. -
Returns the visible collection item cell for the item with uuid.
Declaration
Swift
public func cellForItem(with uuid: String) -> FUIHierarchyCollectionItem?
Parameters
uuid
The uuid of the item which the cell associated with.
Return Value
A
FUIHierarchyViewCollectionItem
object ornil
if 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
open func reloadData()
-
Insert children located at certain indexes into a parent. The parent must be in expanded state.
Declaration
Swift
open func insertChildren(of parent: String, at indexes: IndexSet)
Parameters
parent
The parent that gets new children.
indexes
The indexes at which to insert children.
-
Remove children located at specified indexes from a parent. The parent must be in expanded state.
Declaration
Swift
open func removeChildren(of parent: String, at indexes: IndexSet)
Parameters
parent
The parent from which children are removed.
indexes
The 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
open func invalidateParent(of child: String)
Parameters
child
The 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
open func invalidateChildren(of parent: String)
Parameters
parent
The 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
open func invalidateItems(with uuids: [String])
Parameters
uuids
The uuids of hierarchy items who are invalidated.