Former是一个完全可定制的Swift库,用于轻松创建基于UITableView的表单。
提交问题
点击这里开始提交错误报告。请使用此模板以确保您的错误报告不会因信息不足而被关闭。
提交功能请求
点击这里开始提交功能请求。请使用此模板以确保您的功能请求不会因信息不足而被拒绝。另外请注意,尽管我们希望尽可能让所有人都能胜任,但由于缺乏时间和与插件的定位不符,我们可能无法满足所有的功能请求,您可能需要考虑即使我们同意一个功能对插件有益,也需要进行贡献。
演示
内容
需求
- Xcode 10+
- Swift 4.2+
- iOS 10.0+
仍然想使用 iOS7 和 Swift 2.2 或 2.3 吗?
-> 您可以使用 1.4.0。
安装
CocoaPods
在您的 Podfile 中添加以下行
use_frameworks!
target 'YOUR_TARGET_NAME' do
pod 'Former'
end
Carthage
在您的 Cartfile 中添加以下行
github "ra1028/Former"
用法
您可以同时设置单元格的样式和事件回调。
ViewController和Cell不需要覆盖提供的默认值。
简单示例
import Former
final class ViewController: FormViewController {
override func viewDidLoad() {
super.viewDidLoad()
let labelRow = LabelRowFormer<FormLabelCell>()
.configure { row in
row.text = "Label Cell"
}.onSelected { row in
// Do Something
}
let inlinePickerRow = InlinePickerRowFormer<FormInlinePickerCell, Int>() {
$0.titleLabel.text = "Inline Picker Cell"
}.configure { row in
row.pickerItems = (1...5).map {
InlinePickerItem(title: "Option\($0)", value: Int($0))
}
}.onValueChanged { item in
// Do Something
}
let header = LabelViewFormer<FormLabelHeaderView>() { view in
view.titleLabel.text = "Label Header"
}
let section = SectionFormer(rowFormer: labelRow, inlinePickerRow)
.set(headerViewFormer: header)
former.append(sectionFormer: section)
}
}
RowFormer
RowFormer是管理单元格的类的基类。受RowFormer类管理的单元格应遵循相应的协议。每个RowFormer类都在名为"on*"的函数(例如,onSelected、onValueChanged等)中暴露事件处理。
下面列出了提供的默认RowFormer类及其相应的协议。
使用LabelRowFormer的示例
let labelRow = LabelRowFormer<YourLabelCell>(instantiateType: .Nib(nibName: "YourLabelCell")) {
$0.titleLabel.textColor = .blackColor()
}.configure { row in
row.rowHeight = 44
row.text = "Label Cell"
}.onSelected { row in
print("\(row.text) Selected !!")
}
更新单元格
row.update()
row.update { row in
row.text = "Updated title"
}
row.cellUpdate { cell in
cell.titleLabel.textColor = .redColor()
}
获取单元格实例
let cell = row.cell
print(cell.titleLabel.text)
设置动态行高
row.dynamicRowHeight { tableView, indexPath -> CGFloat in
return 100
}
ViewFormer
ViewFormer是管理HeaderFooterView的类的基类。
受ViewFormer类管理的HeaderFooterView应遵循相应的协议。下面列出了提供的默认ViewFormer类及其相应的协议。
演示 | 类 | 协议 | 默认提供的单元格 |
---|---|---|---|
免费 | CustomViewFormer | 无 | 无 |
LabelViewFormer | LabelFormableView | FormLabelHeaderView 和 FormLabelFooterView |
使用LabelViewFormer的示例
let headerView = LabelViewFormer<YourLabelView>(instantiateType: .Nib(nibName: "YourLabelView")) {
$0.titleLabel.textColor = .blackColor()
}.configure { view in
view.viewHeight = 30
view.text = "Label HeaderFooter View"
}
SectionFormer
SectionFormer是一个表示TableView的节的类。
SectionFormer可以添加、删除行Former,并设置视图Former。
示例
let section = SectionFormer(rowFormer: row1, row2, row3)
.set(headerViewFormer: headerView)
.set(footerViewFormer: footerView)
添加单元格
section.append(rowFormer: row1, row2, row3)
section.add(rowFormers: rows)
section.insert(rowFormer: row, toIndex: 3)
section.insert(rowFormer: row, below: otherRow)
// etc...
删除单元格
section.remove(0)
section.remove(0...5)
section.remove(rowFormer: row)
// etc...
设置头部尾部视图
section.set(headerViewFormer: headerView)
section.set(footerViewFormer: footerView)
Former
Former是一个管理整个表单的类。
以下是一些示例。
添加节或单元格
former.append(sectionFormer: row)
former.add(sectionFormers: rows)
former.insert(sectionFormer: section, toSection: 0)
former.insert(rowFormer: row, toIndexPath: indexPath)
former.insert(sectionFormer: section, above: otherSection)
former.insert(rowFormers: row, below: otherRow)
// etc...
// with animation
former.insertUpdate(sectionFormer: section, toSection: 0, rowAnimation: .Automatic)
former.insertUpdate(rowFormer: row, toIndexPath: indexPath, rowAnimation: .Left)
former.insertUpdate(sectionFormer: section, below: otherSection, rowAnimation: .Fade)
former.insertUpdate(rowFormers: rows, above: otherRow, rowAnimation: .Bottom)
// etc...
删除节或单元格
former.removeAll()
former.remove(rowFormer: row1, row2)
former.remove(sectionFormer: section1, section2)
// etc...
// with animation
former.removeAllUpdate(.Fade)
former.removeUpdate(sectionFormers: sections, rowAnimation: .Middle)
// etc...
选择或取消选择单元格
former.select(indexPath: indexPath, animated: true, scrollPosition: .Middle)
former.select(rowFormer: row, animated: true)
former.deselect(true)
// etc...
结束编辑
former.endEditing()
编辑下一个/上一个单元格
if former.canBecomeEditingNext() {
former.becomeEditingNext()
}
if former.canBecomeEditingPrevious() {
former.becomeEditingPrevious()
}
事件处理设置函数
public func onCellSelected(handler: (NSIndexPath -> Void)) -> Self
public func onScroll(handler: ((scrollView: UIScrollView) -> Void)) -> Self
public func onBeginDragging(handler: (UIScrollView -> Void)) -> Self
public func willDeselectCell(handler: (NSIndexPath -> NSIndexPath?)) -> Self
public func willDisplayCell(handler: (NSIndexPath -> Void)) -> Self
public func willDisplayHeader(handler: (/*section:*/Int -> Void)) -> Self
public func willDisplayFooter(handler: (/*section:*/Int -> Void)) -> Self
public func didDeselectCell(handler: (NSIndexPath -> Void)) -> Self
public func didEndDisplayingCell(handler: (NSIndexPath -> Void)) -> Self
public func didEndDisplayingHeader(handler: (/*section:*/Int -> Void)) -> Self
public func didEndDisplayingFooter(handler: (/*section:*/Int -> Void)) -> Self
public func didHighlightCell(handler: (NSIndexPath -> Void)) -> Self
public func didUnHighlightCell(handler: (NSIndexPath -> Void)) -> Self
自定义能力
ViewController
无需继承FormViewController类。
相反,创建一个UITableView和Former的实例,如下例所示。
final class YourViewController: UIViewController {
private let tableView: UITableView = UITableView(frame: CGRect.zero, style: .Grouped) // It may be IBOutlet. Not forget to addSubview.
private lazy var former: Former = Former(tableView: self.tableView)
...
**单元格** 同样无需继承默认提供的单元格类(如FormLabelCell等);只需符合相应的协议。当然可以使用Nib。以下是一个使用LabelRowFormer的示例
final class YourCell: UITableViewCell, LabelFormableRow {
// MARK: LabelFormableRow
func formTextLabel() -> UILabel? {
return titleLabel
}
func formSubTextLabel() -> UILabel? {
return subTitleLabel
}
func updateWithRowFormer(rowFormer: RowFormer) {
// Do something
}
// MARK: UITableViewCell
var titleLabel: UILabel?
var subTitleLabel: UILabel?
...
**行Former** 如果要创建自定义RowFormer,则让您的类继承自BaseRowFormer并符合Formable协议。
它必须符合ConfigurableInlineForm。在InlineRowFomer的情况下,符合SelectorRowFormer的UpdatableSelectorForm情况。请参阅源代码以获取详细信息。
使用两个UITextFields单元格的RowFormer示例
public protocol DoubleTextFieldFormableRow: FormableRow {
func formTextField1() -> UITextField
func formTextField2() -> UITextField
}
public final class DoubleTextFieldRowFormer<T: UITableViewCell where T: DoubleTextFieldFormableRow>
: BaseRowFormer<T>, Formable {
// MARK: Public
override public var canBecomeEditing: Bool {
return enabled
}
public var text1: String?
public var text2: String?
public required init(instantiateType: Former.InstantiateType = .Class, cellSetup: (T -> Void)? = nil) {
super.init(instantiateType: instantiateType, cellSetup: cellSetup)
}
public final func onText1Changed(handler: (String -> Void)) -> Self {
onText1Changed = handler
return self
}
public final func onText2Changed(handler: (String -> Void)) -> Self {
onText2Changed = handler
return self
}
open override func cellInitialized(cell: T) {
super.cellInitialized(cell)
cell.formTextField1().addTarget(self, action: "text1Changed:", forControlEvents: .EditingChanged)
cell.formTextField2().addTarget(self, action: "text2Changed:", forControlEvents: .EditingChanged)
}
open override func update() {
super.update()
cell.selectionStyle = .None
let textField1 = cell.formTextField1()
let textField2 = cell.formTextField2()
textField1.text = text1
textField2.text = text2
}
// MARK: Private
private final var onText1Changed: (String -> Void)?
private final var onText2Changed: (String -> Void)?
private dynamic func text1Changed(textField: UITextField) {
if enabled {
let text = textField.text ?? ""
self.text1 = text
onText1Changed?(text)
}
}
private dynamic func text2Changed(textField: UITextField) {
if enabled {
let text = textField.text ?? ""
self.text2 = text
onText2Changed?(text)
}
}
}
贡献
如果您有兴趣帮助我们改进和维护Former,强烈建议您分支存储库,并以您的更新提交_pull请求。
如果选择提交_pull请求,请确保在PR描述中清晰地记录您所做的更改。
许可证
Former可在MIT许可证下使用。有关更多信息,请参阅LICENSE文件。