This framework allows you to build Table views using UIKit with syntax similar to SwiftUI

Overview

Jenga - 基于Swift ResultBuilder优雅的构建UITableView

License  Swift  Platform  Swift Package Manager  Cocoapods

🇨🇳 天朝子民

This framework allows you to build Table views using UIKit with syntax similar to SwiftUI. You can think about this as an improved UITableView.

Features

  • 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, use state and binding to bind UI state
  • Support automatic calculation and row height
  • Support automatic registration of Cell
  • Continue to add more new features.

Screenshot

Simple

Setting

Installation

CocoaPods - Podfile

pod 'Jenga'

Swift Package Manager for Apple platforms

Select Xcode menu File > Swift Packages > Add Package Dependency and enter repository URL with GUI.

Repository: https://github.com/fanglinwei/Jenga

Swift Package Manager

Add the following to the dependencies of your Package.swift:

.package(url: "https://github.com/fanglinwei/Jenga", from: "version")

Usage

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:

DSLAutoTable is recommended for fast builds:

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:

Stroke

Custom Cell:

() .height(1540 / 2078 * (UIScreen.main.bounds.width - 32)) .data("image2") .customize { (cell, value) in print(cell, value) } } .headerHeight(20) }">
@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:

Stroke

State and Binding:

    @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(UITableView.automaticDimension)
        
        TableSection(binding: $isHiddenCat) { isOn in
            NavigationRow("🐶")
            NavigationRow("🐶")
            NavigationRow("🐶")
  
            if isOn {
                NavigationRow("🐱")
                NavigationRow("🐱")
                NavigationRow("🐱")
            }
        }
        .header("Animal")
        .headerHeight(UITableView.automaticDimension)
    }

Modify State to update UI

text = "Swift"
detailText = "Jenga"
isShowCat = true

preview:

Stroke Stroke

Section Binding:

() .data($0) .height(44) } .headerHeight(UITableView.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(UITableView.automaticDimension) }">
    @State var emojis: [String] = ["🐶", "🐱", "🐭", "🦁", "🐼"]
    
    // DSL
    @TableBuilder
    var tableBody: [Table] {
        
        TableSection(binding: $emojis) {
            TableRow<EmojiCell>()
                .data($0)
                .height(44)
        }
        .headerHeight(UITableView.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(UITableView.automaticDimension)
    }

preview:

Stroke

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")
    }

自定义DSLAutoTable创建的TableView

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

  1. TableDirector
    lazy var table = TableDirector(tableView, delegate: self)
  2. Describe TableBody using @TableBuilder
        @TableBuilder
        var tableBody: [Table]] {
            
            TableSection(binding: $array) {
                TableRow<EmojiCell>()
                    .data($0)
                    .height(44)
            }
            .headerHeight(UITableView.automaticDimension)
        }
  3. Update TableBody
    table.set(sections: tableBody)

Done, your table is ready.

For more examples, see the sample application.

Cell height calculating strategy:

Implementation ideas come fromFDTemplateLayoutCell

You can set height to UITableView.highAutomaticDimension to enable automatic calculation and cache row height

Just view AutoHeightViewController in Demo

// row
NavigationRow()
	.height(UITableView.highAutomaticDimension)

// section
TableSection {
  rows...
}
.rowHeight(UITableView.highAutomaticDimension)

SystemRow protocol provides chaining

Row 描述
text 标题
detailText 子标题(默认value1)
detailText(.subtitle) 子标题subtitle
detailText(.value1) 子标题value1
detailText(.value2) 子标题value2
detailText(.none) 子标题空样式
isOn 开关
height 行高
estimatedHeight 预估行高
selectionStyle 选中样式
onTap 点击事件
customize 自定义

Contributing

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.

Thanks for inspiration

License

Jenga is under MIT license. See the LICENSE file for more info.

You might also like...
Convenient UITableViewCell subclass that implements a swippable content to trigger actions (similar to the Mailbox app).
Convenient UITableViewCell subclass that implements a swippable content to trigger actions (similar to the Mailbox app).

MCSwipeTableViewCell An effort to show how one would implement a UITableViewCell like the one we can see in the very well executed Mailbox iOS app. Pr

Elegant and easy way to integrate pagination with dummy views
Elegant and easy way to integrate pagination with dummy views

AZTableView Controller Features Automatic pagination handling No more awkward empty TableView screen AZ TableView controller give you advantage to con

Framework to help you better manage UITableViews
Framework to help you better manage UITableViews

UITableView made simple 🙌 Main Features 🙉 Skip the UITableViewDataSource & UITableViewDelegate boilerplate and get right to building your UITableVie

An easy to use UITableViewCell subclass that allows to display swippable buttons with a variety of transitions.
An easy to use UITableViewCell subclass that allows to display swippable buttons with a variety of transitions.

MGSwipeTableCell MGSwipeTableCell is an easy to use UITableViewCell subclass that allows to display swipeable buttons with a variety of transitions. T

APDynamicGrid is a SwiftUI package that helps you create consistent and animatable grids.
APDynamicGrid is a SwiftUI package that helps you create consistent and animatable grids.

APDynamicGrid Overview APDynamicGrid is a SwiftUI package that helps you create consistent and animatable grids. The DynamicGrid View preserves the sa

a TableView have thumbnail cell only, and you can use gesture let it expands other expansionView, all diy
a TableView have thumbnail cell only, and you can use gesture let it expands other expansionView, all diy

ZYThumbnailTableView #####可展开型预览TableView,开放接口,完全自由定制 #####An expandable preview TableView, custom-made all the modules completely with open API you c

Settings screen composing framework
Settings screen composing framework

THIS PROJECT IS NO LONGER MAINTAINED. HERE ARE SOME SUITABLE ALTERNATIVES: SwiftUI Form https://github.com/xmartlabs/Eureka https://github.com/neoneye

Networking layer implementation using CLEAN Architecture for iOS.

NetworkLayer-CLEANArchitecture Networking layer implementation using CLEAN Architecture for iOS. Features ✨ CLEAN Architecture ✨ No Storyboards No ext

ListViewSwiftUI - A project for creating a vertical list using the Swift UI.This project include topic,ListView to show list of movies,Tabbar
Releases(1.2.1)
Owner
Fun
Fake it until you make it。
Fun
Type-safe declarative table views.

TableKit TableKit is a super lightweight yet powerful generic library that allows you to build complex table views in a declarative type-safe manner.

Max Sokolov 694 Dec 13, 2022
Using UI Table View

News-App Table View와 Table view controller Table View : Table의 크기를 지정할 수 있다. Table View Controller: 전체의 뷰가 하나의 테이블 Table View Table view 구성요소 결정하기 어떤

Jiwon 0 Dec 9, 2021
Use Yelp API to fetch restuarants around a location and show them in a table view

Yelp Use Yelp API to fetch restuarants around a location and show them in a table view - Infinite scrolling, Prefetching, Image Caching. Design Patter

null 0 Nov 1, 2021
Typed, yet Flexible Table View Controller

ConfigurableTableViewController Simple view controller that provides a way to configure a table view with multiple types of cells while keeping type s

Arek Holko 270 Oct 15, 2022
A Swift library for swipeable table cells

BWSwipeRevealCell Using the library **Note: Use version 1.0.1 for Swift 2.3 support and version 2.0.0 or higher for Swift 3 support ** There are two m

Kyle Newsome 67 May 11, 2022
Generic table view controller with external data processing

FlexibleTableViewController Swift library of generic table view controller with external data processing of functionality, like determine cell's reuse

Dmytro Pylypenko 9 May 20, 2018
A UITableView extension that enables cell insertion from the bottom of a table view.

ReverseExtension UITableView extension that enabled to insert cell from bottom of tableView. Concept It is difficult to fill a tableview content from

Taiki Suzuki 1.7k Dec 15, 2022
TableViews - Emoji Table View For iOS With Swift

TableViews Hello! This is EmojiTableView. Let me introduce you my first app when

null 0 Jan 2, 2022
An easy-to-use UITableViewCell subclass that implements a swippable content view which exposes utility buttons (similar to iOS 7 Mail Application)

SWTableViewCell An easy-to-use UITableViewCell subclass that implements a swipeable content view which exposes utility buttons (similar to iOS 7 Mail

Christopher Wendel 7.2k Dec 31, 2022