Eureka
是一个纯 Swift
库,它能帮你快速优雅地创建一个 TableView
。这个库本身也提供了大量内置的不同功能的 Cell
,使用上也很简单。如果内置的 Cell
样式或功能不能满足需要,你也可以自定义 Cell
。
使用Eureka设置 TableView
的代码大概是下面这样:
form +++ Section() <<< LabelRow() { $0.title = "LabelRow" $0.value = "Default Value" }.cellSetup({ (cell, row) in cell.accessoryType = .disclosureIndicator }).onCellSelection({ (cell, row) in print("cell selection") })
本文主要介绍 Eureka
的基本使用和自定义 Cell
的步骤。你可以在 这里 查看本文的Demo。
Eureka
的基本使用主要是三步
ViewController
并将 ViewController
设置为 FormViewController
的子类 Section
Row
ViewController
显示 tableView
首先得有一个控制器,这里我们新建一个控制器并将它设置成 FormViewController
的子类,如下所示:
class ViewController: FormViewController { override func viewDidLoad() { super.viewDidLoad() } }
FormViewController
本身是 UIViewController
的子类,而且 Eureka
框架已经在其中添加和设置好了 tableView
,所以我们开发时不用操心布局,仅仅关注交互逻辑就可以了。
Section
FormViewController
里 tableView
的 style
属性值为 .grouped
,这里我们添加多少个 Section
就会自动生成多少个组,添加语法如下:
form +++ Section()
有的人看到这里或许有点奇怪, +++
是个什么语法,好像没见过啊。其实这是 Eureka
使用了Swift自定义运算符的特性,定义 +++
这个中缀运算符,它在源文件里是这么定义的:
infix operator +++ : FormPrecedence
上面这个添加 Section
的语法定义是这样的:
@discardableResult public func +++ (left: Form, right: Section) -> Form { left.append(right) return left }
这里 Form
遵从了 RangeReplaceableCollection
这个协议,重写了 append
这个方法,具体实现有兴趣的可以去看源码。
Row
Row
的创建和设置是所有步骤的核心,所有的交互逻辑都是在这里完成的。 Eureka
内置了数十种常用的 Row
,这里我们添加最常用的三种 Row
:
form +++ Section() <<< LabelRow() { $0.title = "LabelRow" $0.value = "Default Value" }.cellSetup({ (cell, row) in cell.accessoryType = .disclosureIndicator }).onCellSelection({ (cell, row) in print("cell selection") }) <<< TextRow(tag: "TextRow") .cellSetup({ (cell, row) in row.tag = "TextRow" row.title = "TextRow" row.placeholder = "Input your message" }) .cellUpdate({ (cell, row) in print("cell update") }) <<< SwitchRow() { $0.tag = "SwitchValue" $0.title = "SwitchRow" $0.value = true }.onChange({ (row) in print("value changed: /(row.value ?? false)") })
<<<
同样是 Eureka
自定义的中缀运算符,作用是将 Row
添加到对应的 Section
中。在上面的代码中,我是在 Row
的生成方法的闭包中为 title
和 value
赋值,这个操作同样也可以放在 cellSetup
方法中(这个操作只会在 Row
创建时调用),效果是一样的。需要动态刷新的值需要在 cellUpdate
方法中设置。 Eureka
同时也提供了 onCellSelection
和 onChange
这样的响应方法,在里面定义其实响应逻辑即可。
至此, Eureka
的基本使用就全部完成了。如果 Eureka
框架自带的 Row
已经能完全满足你的需求,就不需要往下看了。但如果你不满足于内置 Row
,那么我们继续看看如何自定义 Cell
和 Row
Cell
这里我们来定义一个模拟软件更新的 Cell
,效果图如下:
首先,我们需要一个结构体 Software
方便为 Cell
赋值:
enum UpdateState: Int { case toUpdate = 0 case updating case alreadyNewest } struct Software: Equatable { var name: String var updateState: UpdateState } func == (lhs: Software, rhs: Software) -> Bool { return lhs.name == rhs.name }
这里有一点需要注意的是,定义的类或者结构体必须遵从 Equatable
协议,否则在自定义 Cell
里使用时会报错。
Cell
定义好了结构体,接下来就是实现 Cell
部分。
自定义 Eureka
的 Cell
和自定义普通 UITableView
的 Cell
一样,首先要选择使用纯代码创建还是 xib
创建。这里我们使用 xib
的方式。新建自定义 Cell
,如下图:
自定义布局, Cell
连线, UpdateCell
的代码如下:
final class UpdateCell: Cell<Software>, CellType { @IBOutlet weak var titleLabel: UILabel! @IBOutlet weak var updateButton: UIButton! @IBOutlet weak var aniContainerView: UIView! @IBOutlet weak var noNeedUpdateLabel: UILabel! private var shapeLayer = CAShapeLayer() override func setup() { selectionStyle = .none height = { return 44 } //这里省略布局代码 } override func update() { guard let software = row.value else { return } titleLabel.text = software.name updateUI(software.updateState) } }
在创建 UpdateCell
类的时候,有几点需要注意:
Cell CellType Cell
在上面的代码的, Setup
方法只会在 Cell
创建时调用一次,可以在这里写布局代码,而 Update
方法会在每次刷新的时候调用,可以在这里给 Cell
的 subViews
赋值。
Row
接下来还需要自定义 Row
,从属于上面我们刚刚定义的 Cell
,并在里面加载 xib
:
final class UpdateRow: Row<UpdateCell>, RowType { required init(tag: String?) { super.init(tag: tag) cellProvider = CellProvider<UpdateCell>(nibName: "UpdateCell") } }
Cell
到 Section
中 自定义 Cell
创建完成后,就可以像使用框架中自带的 Row
一样来使用我们的自定义 Row
:
<<< UpdateRow() { $0.value = Software(name: "My Software", updateState: .toUpdate) }
其实 Eureka
的使用比较简单,熟练操作后会是快速构建 UITableView
的利器。本文的Demo可以在 这里 查看。