Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions Examples/TreeView/TreeView.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objectVersion = 60;
objects = {

/* Begin PBXBuildFile section */
083930262618A7FF008E23A9 /* DataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 083930252618A7FF008E23A9 /* DataManager.swift */; };
086D5379262C743A00E7B920 /* Queue-Optimized.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086D5378262C743A00E7B920 /* Queue-Optimized.swift */; };
086D537D262C7A5A00E7B920 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086D537C262C7A5A00E7B920 /* Utils.swift */; };
089A27232607D85A00F907DA /* OutlineItemDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 089A27222607D85A00F907DA /* OutlineItemDataSet.swift */; };
08FD01D526E01B6400902DD3 /* SwiftListTreeDataSource in Frameworks */ = {isa = PBXBuildFile; productRef = 08FD01D426E01B6400902DD3 /* SwiftListTreeDataSource */; };
C14ABAA32913568C5599EFDC /* Pods_TreeView.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0F0E7D30A446750D518E9158 /* Pods_TreeView.framework */; };
D81696802BF39C25009E72D6 /* SwiftListTreeDataStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = D816967D2BF39C25009E72D6 /* SwiftListTreeDataStore.swift */; };
D81696812BF39C25009E72D6 /* SwiftUIListWithSearch.swift in Sources */ = {isa = PBXBuildFile; fileRef = D816967E2BF39C25009E72D6 /* SwiftUIListWithSearch.swift */; };
Expand All @@ -21,6 +20,8 @@
D833408E253842DD00AE6894 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D833408C253842DD00AE6894 /* Main.storyboard */; };
D8334090253842E000AE6894 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D833408F253842E000AE6894 /* Assets.xcassets */; };
D8334093253842E000AE6894 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D8334091253842E000AE6894 /* LaunchScreen.storyboard */; };
D8AD1ADD2D84A79E006E2326 /* TableViewDragAndDropSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8AD1ADC2D84A79E006E2326 /* TableViewDragAndDropSupport.swift */; };
D8CFE6D72D848F8C001CE3C3 /* SwiftListTreeDataSource in Frameworks */ = {isa = PBXBuildFile; productRef = D8CFE6D62D848F8C001CE3C3 /* SwiftListTreeDataSource */; };
D8F4525C2539C8A500F10963 /* TreeViewController+RATreeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8F4525B2539C8A500F10963 /* TreeViewController+RATreeView.swift */; };
D8F452642539C93200F10963 /* OutlineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8F452632539C93200F10963 /* OutlineItem.swift */; };
D8F4526C2539CCE500F10963 /* Cell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D8F4526B2539CCE500F10963 /* Cell.xib */; };
Expand Down Expand Up @@ -51,6 +52,7 @@
D833408F253842E000AE6894 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
D8334092253842E000AE6894 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
D8334094253842E000AE6894 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
D8AD1ADC2D84A79E006E2326 /* TableViewDragAndDropSupport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableViewDragAndDropSupport.swift; sourceTree = "<group>"; };
D8F4525B2539C8A500F10963 /* TreeViewController+RATreeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TreeViewController+RATreeView.swift"; sourceTree = "<group>"; };
D8F452632539C93200F10963 /* OutlineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OutlineItem.swift; sourceTree = "<group>"; };
D8F4526B2539CCE500F10963 /* Cell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = Cell.xib; sourceTree = "<group>"; };
Expand All @@ -67,7 +69,7 @@
buildActionMask = 2147483647;
files = (
C14ABAA32913568C5599EFDC /* Pods_TreeView.framework in Frameworks */,
08FD01D526E01B6400902DD3 /* SwiftListTreeDataSource in Frameworks */,
D8CFE6D72D848F8C001CE3C3 /* SwiftListTreeDataSource in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -159,6 +161,7 @@
D816967F2BF39C25009E72D6 /* SwiftUI */,
D833408A253842DD00AE6894 /* TableController.swift */,
D8F452F6253A44CE00F10963 /* TableWithSearchController.swift */,
D8AD1ADC2D84A79E006E2326 /* TableViewDragAndDropSupport.swift */,
);
path = SwiftListTreeDataSource;
sourceTree = "<group>";
Expand Down Expand Up @@ -198,7 +201,7 @@
);
name = TreeView;
packageProductDependencies = (
08FD01D426E01B6400902DD3 /* SwiftListTreeDataSource */,
D8CFE6D62D848F8C001CE3C3 /* SwiftListTreeDataSource */,
);
productName = test;
productReference = D8334083253842DD00AE6894 /* TreeView.app */;
Expand Down Expand Up @@ -228,7 +231,7 @@
);
mainGroup = D833407A253842DD00AE6894;
packageReferences = (
08FD01D326E01B6400902DD3 /* XCRemoteSwiftPackageReference "SwiftListTreeDataSource" */,
D8CFE6D52D848F8C001CE3C3 /* XCLocalSwiftPackageReference "../../../SwiftListTreeDataSource" */,
);
productRefGroup = D8334084253842DD00AE6894 /* Products */;
projectDirPath = "";
Expand Down Expand Up @@ -311,6 +314,7 @@
D81696802BF39C25009E72D6 /* SwiftListTreeDataStore.swift in Sources */,
D8F4526F2539CCEE00F10963 /* Cell.swift in Sources */,
089A27232607D85A00F907DA /* OutlineItemDataSet.swift in Sources */,
D8AD1ADD2D84A79E006E2326 /* TableViewDragAndDropSupport.swift in Sources */,
D8334087253842DD00AE6894 /* AppDelegate.swift in Sources */,
D8F452CA2539DDAE00F10963 /* OutlineViewController.swift in Sources */,
D8334089253842DD00AE6894 /* SceneDelegate.swift in Sources */,
Expand Down
17 changes: 8 additions & 9 deletions Examples/TreeView/TreeView/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Kwx-Mc-2Tw">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Kwx-Mc-2Tw">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/>
<capability name="Image references" minToolsVersion="12.0"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
Expand Down Expand Up @@ -122,12 +122,12 @@
</objects>
<point key="canvasLocation" x="-600" y="854"/>
</scene>
<!--Custom Impl.-->
<!--ListTree-->
<scene sceneID="8Ix-7f-X19">
<objects>
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="GpI-76-PuZ" sceneMemberID="viewController">
<tabBarItem key="tabBarItem" title="Custom Impl." image="bicycle" catalog="system" id="Lbb-pp-xah">
<imageReference key="selectedImage" image="bicycle" catalog="system" symbolScale="default"/>
<tabBarItem key="tabBarItem" title="ListTree" image="tree" catalog="system" id="Lbb-pp-xah">
<imageReference key="selectedImage" image="tree" catalog="system" symbolScale="default"/>
</tabBarItem>
<toolbarItems/>
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="E8C-nG-mm2">
Expand Down Expand Up @@ -234,11 +234,11 @@
</objects>
<point key="canvasLocation" x="788" y="854"/>
</scene>
<!--Custom Impl + Search-->
<!--ListTree + Search-->
<scene sceneID="iBS-rT-2Xa">
<objects>
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="5k0-U2-vzr" sceneMemberID="viewController">
<tabBarItem key="tabBarItem" title="Custom Impl + Search" image="bicycle.circle" catalog="system" selectedImage="bicycle.circle" id="DeF-lG-NrV"/>
<tabBarItem key="tabBarItem" title="ListTree + Search" image="tree" catalog="system" selectedImage="tree" id="DeF-lG-NrV"/>
<toolbarItems/>
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="J9u-XJ-USg">
<rect key="frame" x="0.0" y="48" width="414" height="44"/>
Expand Down Expand Up @@ -286,10 +286,9 @@
</scenes>
<resources>
<image name="applelogo" catalog="system" width="105" height="128"/>
<image name="bicycle" catalog="system" width="128" height="78"/>
<image name="bicycle.circle" catalog="system" width="128" height="123"/>
<image name="shippingbox.fill" catalog="system" width="128" height="123"/>
<image name="swiftdata" catalog="system" width="128" height="108"/>
<image name="tree" catalog="system" width="128" height="118"/>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
Expand Down
5 changes: 3 additions & 2 deletions Examples/TreeView/TreeView/Common/Cell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ class Cell: UITableViewCell {
func configure(with item: ListTreeDataSource<OutlineItem>.TreeItemType, searchText: String? = nil) {
let left = 11 + 10 * item.level

let mattrString = NSMutableAttributedString(string: item.value.title, attributes: [ .foregroundColor: UIColor.black ])
let mattrString = NSMutableAttributedString(string: item.value.title, attributes: [ .foregroundColor: UIColor.label ])
if let searchText = searchText, !searchText.isEmpty {
let range = (item.value.title.lowercased() as NSString).range(of: searchText.lowercased())
mattrString.addAttributes([
.font: UIFont.systemFont(ofSize: 17, weight: .semibold)
.font: UIFont.systemFont(ofSize: 17, weight: .semibold),
.foregroundColor: UIColor.tintColor
], range: range)
}

Expand Down
5 changes: 3 additions & 2 deletions Examples/TreeView/TreeView/Common/OutlineItem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import Foundation

class OutlineItem: Hashable {
class OutlineItem: Identifiable, Hashable, Codable {
let title: String
var subitems: [OutlineItem]

Expand All @@ -22,7 +22,8 @@ class OutlineItem: Hashable {
static func == (lhs: OutlineItem, rhs: OutlineItem) -> Bool {
return lhs.identifier == rhs.identifier
}
private let identifier = UUID()
private var identifier = UUID()
var id: UUID { identifier }
}

extension OutlineItem: CustomStringConvertible {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class TreeViewController: UIViewController, RATreeViewDelegate, RATreeViewDataSo
override func viewDidLoad() {
super.viewDidLoad()

view.backgroundColor = .white
view.backgroundColor = .systemBackground
setupTreeView()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ class TableController: UITableViewController {
addItems(items, to: dataSource)
return dataSource
}()

var dragAndDropController: TableViewDragAndDropSupport<OutlineItem>!

@available(iOS 13.0, *)
private(set) lazy var diffableDataSource: UITableViewDiffableDataSource<Section, TreeItemType> = {
return self.createDiffableDataSource()
Expand All @@ -40,11 +41,12 @@ class TableController: UITableViewController {

setupTableView()
setupDataSource()
configureDragAndDrop()
}

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
reloadUI()
updateUI()
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
Expand All @@ -60,7 +62,8 @@ class TableController: UITableViewController {
cell.lbl?.text = item.value.title
cell.lblLeadingConstraint.constant = CGFloat(left)
cell.disclosureImageView.isHidden = item.subitems.isEmpty

cell.contentView.backgroundColor = .systemBackground

let transform = CGAffineTransform.init(rotationAngle: item.isExpanded ? CGFloat.pi/2.0 : 0)
cell.disclosureImageView.transform = transform

Expand All @@ -79,9 +82,30 @@ class TableController: UITableViewController {
}
}

self.reloadUI(animating: true)
self.updateUI(animating: true)
}


// MARK: - Row Swipe to Delete
/// Provide a trailing swipe action for "Delete"
override func tableView(_ tableView: UITableView,
trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath)
-> UISwipeActionsConfiguration? {

let node = listTreeDataSource.items[indexPath.row]

let deleteAction = UIContextualAction(style: .destructive, title: "Delete") { [weak self] _, _, complete in
guard let self = self else { return }

// Deleting a node also removes its entire subtree
self.listTreeDataSource.delete([node.value])
self.listTreeDataSource.reload()
self.updateUI(animating: true)

complete(true)
}
return UISwipeActionsConfiguration(actions: [deleteAction])
}

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
Expand All @@ -103,27 +127,38 @@ extension TableController {
self.tableView.dataSource = self
}
}
func reloadUI(animating: Bool = true) {

func updateUI(animating: Bool = true, reloadIds: [ListTreeDataSource<OutlineItem>.TreeItemType] = []) {
if isOS13Available {
var diffableSnaphot = NSDiffableDataSourceSnapshot<Section, TreeItemType>()
var diffableSnaphot = NSDiffableDataSourceSnapshot<Section, ListTreeDataSource<OutlineItem>.TreeItemType>()
diffableSnaphot.appendSections([.main])
diffableSnaphot.appendItems(listTreeDataSource.items, toSection: .main)
diffableSnaphot.reloadItems(reloadIds)
self.diffableDataSource.apply(diffableSnaphot, animatingDifferences: animating)
} else {
self.tableView.reloadData()
}
}

private func configureDragAndDrop() {
dragAndDropController = TableViewDragAndDropSupport(dataSource: self.listTreeDataSource, tableView: self.tableView, updateUI: { [weak self] animating, reloadIds in
self?.updateUI(animating:animating, reloadIds:reloadIds)
})
tableView.dragInteractionEnabled = true
tableView.dragDelegate = dragAndDropController
tableView.dropDelegate = dragAndDropController
}
}

// MARK: - Actions
fileprivate extension TableController {
@IBAction func collapseAll(_ sender: UIBarButtonItem) {
listTreeDataSource.collapseAll()
reloadUI(animating: false) // `false` to stay on the safe side for batch update in large data set
updateUI(animating: false) // `false` to stay on the safe side for batch update in large data set
}
@IBAction func expandAll(_ sender: UIBarButtonItem) {
listTreeDataSource.expandAll()
reloadUI(animating: false) // `false` to stay on the safe side for batch update in large data set
updateUI(animating: false) // `false` to stay on the safe side for batch update in large data set
}
}

Expand Down
Loading