Skip to content

Latest commit

 

History

History
386 lines (272 loc) · 9.45 KB

README_CN.md

File metadata and controls

386 lines (272 loc) · 9.45 KB

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

License  Swift  Platform  Swift Package Manager  Cocoapods

该框架允许您使用 UIKit 构建 Table 视图,其语法类似于 SwiftUI。 您可以将其视为改进的 UITableView

特性

  • 使用声明式链式语法构建列表 流畅的编码体验 优雅自然的样式设置.
  • 丰富的 Cell 类型支持,支持系统设置样式和自定义类型。
  • 支持@propertyWrapper,使用statebinding绑定UI状态
  • 支持自动计算行高
  • 支持自动注册Cell
  • 更多新特性的不断加入.

截屏

Simple

Setting

安装

CocoaPods - Podfile

pod 'Jenga'

选择 Xcode 菜单 File > Swift Packages > Add Package Dependency 输入仓库地址.

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

将以下内容添加到你的 Package.swift:

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

使用

首先导入

import Jenga

初始化

JengaEnvironment.isEnabledLog = true  //日志
JengaEnvironment.setup(JengaProvider())

然后你只需要简短的代码就可以构建UITableView

	@TableBuilder
	var tableBody: [Table] {
		rows...
	}

下面是一些简单示例. 支持所有设备和模拟器:

推荐使用DSLAutoTable进行快速构建:

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

预览

Stroke

自定义Cell:

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

预览

Stroke

状态以及绑定:

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

修改State更新UI:

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

预览

Stroke Stroke

Section Binding:

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

预览

Stroke

也可以不使用 TableSection,但我仍在权衡这种 API 方法的优缺点

    @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())

如果你想要监听UIScrollViewDelegate或者自行创建TableView, 可以不使用DSLAutoTable协议

在Demo中查看CustomTableViewController即可

  1. 创建 TableDirector
    lazy var table = TableDirector(tableView, delegate: self)
  2. 使用TableBuilder描述Contents
        @TableBuilder
        var tableBody: [Table]] {
            
            TableSection(binding: $array) {
                TableRow<EmojiCell>()
                    .data($0)
                    .height(44)
            }
            .headerHeight(.automaticDimension)
        }
  3. 更新TableBody
    table.set(sections: tableBody)

好了 你的列表完成了

更多示例请查看工程应用.

自动计算缓存行高:

实现思路来源于FDTemplateLayoutCell

你可以设置高度为RowHeight.highAutomaticDimension来开启自动计算并且缓存行高

在Demo中查看AutoHeightViewController即可

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

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

SystemRow的协议提供链式

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

贡献

如果您需要实现特定功能或遇到错误,请打开issue。 如果您自己扩展了Jenga的功能并希望其他人也使用它,请提交拉取请求。

思路来源

协议

Jenga 使用 MIT 协议. 有关更多信息,请参阅LICENSE文件.