This framework allows you to build Table views using UIKit with syntax similar to SwiftUI. You can think about this as an improved UITableView
.
- Use declarative chaining syntax to build lists Smooth coding experience Elegant and natural styling.
- Rich Cell type support, support system setting styles and custom types.
- Support
@propertyWrapper
, usestate
andbinding
to bind UI state - Support automatic calculation and row height
- Support automatic registration of Cell
- Continue to add more new features.
pod 'Jenga'
Select Xcode menu File > Swift Packages > Add Package Dependency
and enter repository URL with GUI.
Repository: https://github.com/fanglinwei/Jenga
Add the following to the dependencies of your Package.swift
:
.package(url: "https://github.com/fanglinwei/Jenga.git", from: "version")
First make sure to import the framework:
import Jenga
How to initialize:
JengaEnvironment.isEnabledLog = true //日志
JengaEnvironment.setup(JengaProvider())
Then you just need short code to build UITableView
@TableBuilder
var tableBody: [Table] {
rows...
}
Here are some usage examples. All devices are also available as simulators:
import Jenga
class ViewController: UIViewController, DSLAutoTable {
@TableBuilder
var tableBody: [Table] {
TableSection {
NavigationRow("设置样式")
.onTap(on: self) { (self) in
self.navigationController?.pushViewController(SettingViewController(), animated: true)
}
NavigationRow("自定义Cell")
.onTap(on: self) { (self) in
self.navigationController?.pushViewController(CustomViewController(), animated: true)
}
}
}
}
preview:
@TableBuilder
var tableBody: [Table] {
TableSection {
TableRow<BannerCell>("image1")
.height(1184 / 2256 * (UIScreen.main.bounds.width - 32))
.customize { [weak self] cell in
cell.delegate = self
}
SpacerRow(10)
TableRow<BannerCell>()
.height(1540 / 2078 * (UIScreen.main.bounds.width - 32))
.data("image2")
.customize { (cell, value) in
print(cell, value)
}
}
.headerHeight(20)
}
preview:
@State var text = "objective-c"
@State var detailText = "TableView"
@State var isHiddenCat = false
// DSL
@TableBuilder
var tableBody: [Table] {
TableSection {
NavigationRow($text)
.detailText($detailText)
ToggleRow("显示小猫", isOn: $isHiddenCat)
.onTap(on: self) { (self, isOn) in
self.isHiddenCat = isOn
}
}
.header("Toggle")
.rowHeight(52)
.headerHeight(.automaticDimension)
TableSection(binding: $isHiddenCat) { isOn in
NavigationRow("🐶")
NavigationRow("🐶")
NavigationRow("🐶")
if isOn {
NavigationRow("🐱")
NavigationRow("🐱")
NavigationRow("🐱")
}
}
.header("Animal")
.headerHeight(.automaticDimension)
}
Modify State
to update UI
text = "Swift"
detailText = "Jenga"
isShowCat = true
preview:
@State var emojis: [String] = ["🐶", "🐱", "🐭", "🦁", "🐼"]
// DSL
@TableBuilder
var tableBody: [Table] {
TableSection(binding: $emojis) {
TableRow<EmojiCell>()
.data($0)
.height(44)
}
.headerHeight(.automaticDimension)
TableSection {
TapActionRow("Random")
.onTap(on: self) { (self) in
guard self.emojis.count > 3 else { return }
self.emojis[2] = randomEmojis[Int.random(in: 0 ... 4)]
self.emojis[3] = randomEmojis[Int.random(in: 0 ... 4)]
}
TapActionRow("+")
.onTap(on: self) { (self) in
self.emojis.append(randomEmojis[Int.random(in: 0 ... 4)])
}
TapActionRow("-")
.onTap(on: self) { (self) in
guard self.emojis.count > 0 else { return }
_ = self.emojis.popLast()
}
}
.headerHeight(.automaticDimension)
}
preview:
It is also possible not to use TableSection, but I am still weighing the pros and cons of this API approach:
@TableBuilder
var tableBody: [Table] {
TableHeader("我是头部")
NavigationRow("设置样式")
NavigationRow("自定义Cell")
NavigationRow("自定义TableView")
TableFooter("我是底部")
TableHeader("第二组")
.height(100)
NavigationRow("cell")
}
struct JengaProvider: Jenga.JengaProvider {
func defaultTableView(with frame: CGRect) -> UITableView {
let tableView: UITableView
if #available(iOS 13.0, *) {
tableView = UITableView(frame: frame, style: .insetGrouped)
} else {
tableView = UITableView(frame: frame, style: .grouped)
}
return tableView
}
}
JengaEnvironment.setup(JengaProvider())
If you want to listen to UIScrollViewDelegate
or create your own TableView, you can't use DSLAutoTable
protocol
Just view CustomTableViewController
in Demo
-
lazy var table = TableDirector(tableView, delegate: self)
-
@TableBuilder var tableBody: [Table]] { TableSection(binding: $array) { TableRow<EmojiCell>() .data($0) .height(44) } .headerHeight(.automaticDimension) }
-
table.set(sections: tableBody)
Done, your table is ready.
For more examples, see the sample application.
Implementation ideas come fromFDTemplateLayoutCell
You can set height to RowHeight.highAutomaticDimension
to enable automatic calculation and cache row height
Just view AutoHeightViewController
in Demo
// row
NavigationRow()
.height(.highAutomaticDimension)
// section
TableSection {
rows...
}
.rowHeight(.highAutomaticDimension)
modify | description |
---|---|
text |
|
detailText |
UITableViewCell.CellStyle.value1 |
detailText(.subtitle) |
UITableViewCell.CellStyle.subtitle |
detailText(.value1) |
UITableViewCell.CellStyle.value1 |
detailText(.value2) |
UITableViewCell.CellStyle.value2 |
detailText(.none) |
no detailText |
isOn |
switch |
height |
constant(CGFloat), automaticDimension, highAutomaticDimension |
estimatedHeight |
constant(CGFloat), automaticDimension, highAutomaticDimension |
selectionStyle |
|
onTap |
cell didSelected |
customize |
modify cell |
textAlignment |
TapActionRow text alignment |
accessoryType |
NavigationRow accessoryType |
If you have the need for a specific feature that you want implemented or if you experienced a bug, please open an issue. If you extended the functionality of Jenga yourself and want others to use it too, please submit a pull request.
Jenga is under MIT license. See the LICENSE file for more info.