Side Bar
-
A
FUISideBar<Data>is a generic view that displaying data in an expandable list within a side bar.Usage
Initialization:
Implement a data model for the expandable list that will be displayed in side bar.
struct BarItem: Identifiable, Hashable { let id = UUID() let title: String var icon: UIImage? var filledIcon: UIImage? var subtitle: String? var status: UIImage? let children: [BarItem]? func hash(into hasher: inout Hasher) { hasher.combine(self.id) hasher.combine(self.title) } static func == (lhs: BarItem, rhs: BarItem) -> Bool { lhs.id == rhs.id } init(title: String, icon: UIImage? = nil, filledIcon: UIImage? = nil, subtitle: String? = nil, status: UIImage? = nil, children: [BarItem]? = nil) { self.title = title self.icon = icon self.filledIcon = filledIcon self.subtitle = subtitle self.status = status self.children = children } } let items: [BarItem] = [ BarItem(title: "Root Item 0.1", icon: UIImage(systemName: "cloud.snow"), subtitle: "9,999+", status: UIImage(systemName: "clock"), children: nil), BarItem(title: "Root Item 0.4", icon: UIImage(systemName: "cloud.snow"), children: nil), BarItem(title: "Group 1", children: [ BarItem(title: "Child Item 1.1", icon: UIImage(systemName: "square.and.pencil"), subtitle: "66", status: UIImage(systemName: "circle"), children: nil), BarItem(title: "Child Item 1.2", icon: UIImage(systemName: "square.and.pencil"), status: UIImage(systemName: "circle"), children: nil) ]), BarItem(title: "Group 2", children: [ BarItem(title: "Child Item 2.1", icon: UIImage(systemName: "folder"), subtitle: "5", status: UIImage(systemName: "mail"), children: nil) ]) ]Initialize an
FUISideBarwith the data model, a binding of row content view, and the initially selected item. Please note, with this initializer, the sidebar does not support editing.let sidebar = FUISideBar(data: items, children: \.children, rowContent: { item in FUISideBarListItem(icon: item.icon, filledIcon: item.filledIcon, title: item.title, subtitle: item.subtitle, accessoryIcon: item.status) }, selectedItem: items.first)Or, Initialize an
FUISideBarwith the data model, you will need to provide an array ofFUISideBarItemModel, a binding of row content view, and the initially selected item. With this initializer, the sidebar support editing.struct BarItem: FUISideBarItemModel { var id: UUID = UUID() var title: String var icon: UIImage? var filledIcon: UIImage? var subtitle: String? var status: UIImage? var isInvisible: Bool var children: [any FUISideBarItemModel]? static func == (lhs: EditableBarItem, rhs: EditableBarItem) -> Bool { lhs.id == rhs.id } func hash(into hasher: inout Hasher) { hasher.combine(self.id) hasher.combine(self.title) } init(title: String, icon: UIImage? = nil, filledIcon: UIImage? = nil, subtitle: String? = nil, status: UIImage? = nil, children: [EditableBarItem]? = nil, isInvisible: Bool = false) { self.title = title self.icon = icon self.filledIcon = filledIcon self.subtitle = subtitle self.status = status self.children = children self.isInvisible = isInvisible } } let items: [BarItem] = [ BarItem(title: "Root Item 0.1", icon: UIImage(systemName: "square.dashed), filledIcon: UIImage(systemName: "square.dashed.inset.filled"), subtitle: "9,999+", status: UIImage(systemName: "clock"), children: nil), BarItem(title: "Root Item 0.4", icon: UIImage(systemName: "cloud.snow"), children: nil), BarItem(title: "Group 1", children: [ BarItem(title: "Child Item 1.1", icon: UIImage(systemName: "square.and.pencil"), subtitle: "66", status: UIImage(systemName: "circle"), children: nil), BarItem(title: "Child Item 1.2", icon: UIImage(systemName: "square.and.pencil"), status: UIImage(systemName: "circle"), children: nil) ]), BarItem(title: "Group 2", children: [ BarItem(title: "Child Item 2.1", icon: UIImage(systemName: "folder"), subtitle: "5", status: UIImage(systemName: "mail"), children: nil) ]) ] let sidebar = FUISideBar(data: items, rowContent: { item in FUISideBarListItem(icon: item.icon, filledIcon: item.filledIcon, title: item.title, subtitle: item.subtitle, accessoryIcon: item.status) }, selectedItem: items.first)Selection Handler:
A
selectionDidChangeclosure may be used to custom the handling of an selected data element.sidebar.selectionDidChange = { [weak self] item in self?.presentationDidChange?(item) }Handle Editing:
An ‘isEditing’ property of
FUISideBar<Data>indicates whether the sidebar is in editing mode or not. Please note, it is essential to use the corresponding Initialize method which permits the editing of the sidebar. Additionally, an ‘Edit’ button can be added to the navigation bar to allow the sidebar to transition from editing mode to the view model.self.navigationItem.rightBarButtonItem = self.editButtonItem override func setEditing(_ editing: Bool, animated: Bool) { super.setEditing(editing, animated: animated) self.sideBar?.isEditing = editing configNavBarStyle() configureSearchBarOnNavBar(true) }Monitor changed data:
A
dataChangeclosure may be used to receive notifications when the sidebar transitions from its editing mode to the view model if the sidebar item was reordered or visible was changed. This arrangement facilitates effective monitoring and management of changes. This should be used exclusively when the sidebar supports editing and you are particularly concerned about the modified data.sideBar?.dataChange = { (items: [BarItem]) in // Check data changes }Handle Search:
A ‘queryString’ property of
FUISideBar<Data>is used to trigger the searching on SideBar. You can add theFUISearchControlleras navigation item for searching and get the query string from UISearchResultsUpdating.
See morelet fuiSearchController = addResultsController ? FUISearchController(searchResultsController: SearchResultsViewController()) : FUISearchController(searchResultsController: nil) fuiSearchController.searchResultsUpdater = self fuiSearchController.hidesNavigationBarDuringPresentation = hidesNavBar fuiSearchController.setsNavigationBarColor = true fuiSearchController.setsStatusBarStyle = true fuiSearchController.searchBar.placeholderText = "Search" fuiSearchController.searchBar.delegate = self self.searchController = fuiSearchController navigationItem.searchController = searchController navigationItem.hidesSearchBarWhenScrolling = true // false func updateSearchResults(for searchController: UISearchController) { self.sideBar?.queryString = searchController.searchBar.text }Declaration
Swift
@available(iOS 14, *) @MainActor open class FUISideBar<Data>: UIView where Data: RandomAccessCollection, Data.Element: Identifiable & Hashable -
A view for each list item in the
See moreFUISideBarDeclaration
Swift
@available(iOS 14, *) @MainActor open class FUISideBarListItem : FUITintableDrawingView<FUIControlState>, FUITitleMultiLineComponent, FUISubtitleMultiLineComponent, FUILeadingImageViewComponent, FUITrailingImageViewComponent