Skip to content

Commit 60c3e0c

Browse files
committed
Add typed sorting API with DataTableColumn.isSortable
- Add isSortable property to DataTableColumn for per-column control - Add TypedSorting demo showing typed API usage - Add comprehensive tests for typed sorting behavior - Update documentation for column sorting features
1 parent 87adc79 commit 60c3e0c

File tree

12 files changed

+2047
-187
lines changed

12 files changed

+2047
-187
lines changed

Example/DemoSwiftDataTables/App/MenuTableViewController.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ class MenuViewController: UITableViewController {
107107
// Section 5: Sorting & Selection
108108
[
109109
MenuItem(title: "Default Sorting"),
110+
MenuItem(title: "Typed Sorting"),
110111
MenuItem(title: "Column Sortability"),
111112
MenuItem(title: "Sorting Indicator Visibility"),
112113
MenuItem(title: "Row Selection"),
@@ -261,10 +262,12 @@ extension MenuViewController {
261262
case 0:
262263
show(DefaultSortingDemoViewController(), sender: self)
263264
case 1:
264-
show(ColumnSortabilityDemoViewController(), sender: self)
265+
show(TypedSortingDemoViewController(), sender: self)
265266
case 2:
266-
show(SortingIndicatorVisibilityDemoViewController(), sender: self)
267+
show(ColumnSortabilityDemoViewController(), sender: self)
267268
case 3:
269+
show(SortingIndicatorVisibilityDemoViewController(), sender: self)
270+
case 4:
268271
show(RowSelectionDemoViewController(), sender: self)
269272
default:
270273
break
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
//
2+
// TypedSortingDemoViewController.swift
3+
// SwiftDataTables
4+
//
5+
// Created by Pavan Kataria on 29/01/2026.
6+
// Copyright © 2016-2026 Pavan Kataria. All rights reserved.
7+
//
8+
9+
import UIKit
10+
import SwiftDataTables
11+
12+
/// Demo showcasing typed sorting: formatted display values that sort by their underlying type.
13+
///
14+
/// This demo shows how columns like "$1,234.56" can display formatted strings
15+
/// while still sorting numerically by the underlying value.
16+
final class TypedSortingDemoViewController: UIViewController {
17+
18+
// MARK: - Model
19+
20+
private struct Product: Identifiable {
21+
let id: Int
22+
let name: String
23+
let price: Double
24+
let quantity: Int
25+
let lastUpdated: Date
26+
27+
var total: Double { price * Double(quantity) }
28+
}
29+
30+
// MARK: - Data
31+
32+
private let products: [Product] = [
33+
Product(id: 1, name: "Widget", price: 29.99, quantity: 100, lastUpdated: Date().addingTimeInterval(-86400 * 5)),
34+
Product(id: 2, name: "Gadget", price: 9.99, quantity: 500, lastUpdated: Date().addingTimeInterval(-86400 * 2)),
35+
Product(id: 3, name: "Appliance", price: 199.99, quantity: 10, lastUpdated: Date().addingTimeInterval(-86400 * 10)),
36+
Product(id: 4, name: "Tool", price: 49.99, quantity: 75, lastUpdated: Date().addingTimeInterval(-86400 * 1)),
37+
Product(id: 5, name: "Equipment", price: 149.99, quantity: 25, lastUpdated: Date().addingTimeInterval(-86400 * 7)),
38+
Product(id: 6, name: "Device", price: 79.99, quantity: 200, lastUpdated: Date().addingTimeInterval(-86400 * 3)),
39+
Product(id: 7, name: "Component", price: 4.99, quantity: 1000, lastUpdated: Date()),
40+
Product(id: 8, name: "Module", price: 249.99, quantity: 5, lastUpdated: Date().addingTimeInterval(-86400 * 15)),
41+
]
42+
43+
// MARK: - Columns
44+
45+
/// Columns demonstrating different typed sorting approaches
46+
private lazy var columns: [DataTableColumn<Product>] = [
47+
// Simple keypath - sorts by name alphabetically
48+
.init("Name", \.name),
49+
50+
// KeyPath + Format: displays "$29.99", sorts numerically by 29.99
51+
.init("Price", \.price) { "$\(String(format: "%.2f", $0))" },
52+
53+
// Simple keypath for quantity
54+
.init("Qty", \.quantity),
55+
56+
// Computed value: displays total, sorts by computed total
57+
.init("Total", sortedBy: { $0.total }) { product in
58+
"$\(String(format: "%.2f", product.total))"
59+
},
60+
61+
// Date formatting: displays "Jan 29", sorts chronologically
62+
.init("Updated", \.lastUpdated) { date in
63+
let formatter = DateFormatter()
64+
formatter.dateFormat = "MMM d"
65+
return formatter.string(from: date)
66+
},
67+
]
68+
69+
// MARK: - UI
70+
71+
private let instructions = InstructionsView(
72+
description: "Typed sorting: formatted values sort by their underlying type. Price displays '$29.99' but sorts numerically. Total is computed. Dates display abbreviated but sort chronologically.",
73+
config: "Tap column headers to sort. Notice Price and Total sort numerically, not alphabetically."
74+
)
75+
76+
private lazy var dataTable: SwiftDataTable = {
77+
var config = DataTableConfiguration()
78+
config.shouldContentWidthScaleToFillFrame = false
79+
80+
let table = SwiftDataTable(data: products, columns: columns, options: config)
81+
table.translatesAutoresizingMaskIntoConstraints = false
82+
table.backgroundColor = UIColor(red: 235/255, green: 235/255, blue: 235/255, alpha: 1)
83+
return table
84+
}()
85+
86+
// MARK: - Lifecycle
87+
88+
override func viewDidLoad() {
89+
super.viewDidLoad()
90+
title = "Typed Sorting"
91+
view.backgroundColor = .systemBackground
92+
93+
view.addSubview(instructions)
94+
view.addSubview(dataTable)
95+
96+
NSLayoutConstraint.activate([
97+
instructions.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 12),
98+
instructions.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
99+
instructions.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
100+
101+
dataTable.topAnchor.constraint(equalTo: instructions.bottomAnchor, constant: 12),
102+
dataTable.leadingAnchor.constraint(equalTo: view.leadingAnchor),
103+
dataTable.trailingAnchor.constraint(equalTo: view.trailingAnchor),
104+
dataTable.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
105+
])
106+
}
107+
}

0 commit comments

Comments
 (0)