FUIHierarchyViewController

open class FUIHierarchyViewController : UIViewController, FUIHierarchyViewDataSource, FUIHierarchyViewDelegate

A view controller which specializes in managing a hierarchy view. When FUIHierarchyViewController initiates, it sets data source and delegate of hierarchy view to self.

Components

  • hierarchyView

Usage

Subclass FUIHierarchyViewController when you need to show a hierarchy view. It conforms to FUIHierarchyViewDataSource and FUIHierarchyViewDelegate by default.

class MyController: FUIHierarchyViewController {}

Override viewDidLoad and do some setup here. You should register your custom cell if needed. Otherwise hierarchy view will use FUIHierarchyCollectionItem by default.

override func viewDidLoad() {
    super.viewDidLoad()
    hierarchyView.register(YourCustomCollectionViewCell.self, forCellWithReuseIdentifier: "ReuseIdentifierForYourCustomCell")
    // do more setup here.
}

Implement dataSource and 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:

fdlHierarchyViewController_hierarchyView {}