用于节索引,并使用他的逻辑。在使用标题视图上的tapgesture时,您可以获取节索引。objc_setAssociatedObject
objc_getAssociatedObject.
UITapGestureRecognizer *singleTapRecogniser = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(gestureHandler:)] autorelease];
[singleTapRecogniser setDelegate:self];
singleTapRecogniser.numberOfTouchesRequired = 1;
singleTapRecogniser.numberOfTapsRequired = 1;
[sectionHeaderView addGestureRecognizer:singleTapRecogniser];
为了使它更加通用,表格的项不应该从专门为扩展功能而专门设计的类中继承,而是应该有一个定义必要属性的协议
我们可以扩展的级别数量上不应该有限制。因此,表格可以具有选项、子选项、子子选项等。
表格视图应使用任何常用动画(而不是reloadData
)来显示或隐藏单元格
扩展操作不一定要附加到用户选择单元格上,例如单元格可以有一个UISwitch
实现的简化版本(https://github.com/JuanjoArreola/ExpandableCells)如下:
首先是协议:
protocol CellDescriptor: class {
var count: Int { get }
var identifier: String! { get }
}
extension CellDescriptor {
var count: Int { return 1 }
}
protocol ExpandableCellDescriptor: CellDescriptor {
var active: Bool { get set }
var children: [CellDescriptor] { get set }
subscript(index: Int) -> CellDescriptor? { get }
func indexOf(cellDescriptor: CellDescriptor) -> Int?
}
Swift 的一个很酷的特性是我们可以在协议扩展中编写一些实现,所有符合协议的类都可以使用默认实现,因此我们可以像这样编写 count
、subscript
和 indexOf
实现,以及其他一些有用的函数:
extension ExpandableCellDescriptor {
var count: Int {
var total = 1
if active {
children.forEach({ total += $0.count })
}
return total
}
var countIfActive: Int {
...
}
subscript(index: Int) -> CellDescriptor? {
...
}
func indexOf(cellDescriptor: CellDescriptor) -> Int? {
...
}
func append(cellDescriptor: CellDescriptor) {
children.append(cellDescriptor)
}
}
class ExpandableOption: ExpandableCellDescriptor {
var delegate: ExpandableCellDelegate?
var identifier: String!
var active: Bool = false {
didSet {
delegate?.expandableCell(self, didChangeActive: active)
}
}
var children: [CellDescriptor] = []
var title: String?
}
这是UITableViewCell的一个子类:
class SwitchTableViewCell: UITableViewCell, CellDescrptionConfigurable {
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var switchControl: UISwitch!
var cellDescription: CellDescriptor! {
didSet {
if let option = cellDescription as? ExpandableOption {
titleLabel.text = option.title
switchControl.on = option.active
}
}
}
@IBAction func activeChanged(sender: UISwitch) {
let expandableCellDescriptor = cellDescription as! ExpandableCellDescriptor
expandableCellDescriptor.active = sender.on
}
}
请注意,您可以根据自己的喜好配置单元格及其类,可以添加图像、标签、开关等等;没有限制,也不需要更改协议。
最后,在TableViewController中创建选项树:
var options = CellDescriptionArray()
override func viewDidLoad() {
super.viewDidLoad()
let account = ExpandableOption(identifier: "ExpandableCell", title: "Account")
let profile = Option(identifier: "SimpleCell", title: "Profile")
let isPublic = ExpandableOption(identifier: "SwitchCell", title: "Public")
let caption = Option(identifier: "SimpleCell", title: "Anyone can see this account")
isPublic.append(caption)
account.append(profile)
account.append(isPublic)
options.append(account)
let group = ExpandableOption(identifier: "ExpandableCell", title: "Group")
group.append(Option(identifier: "SimpleCell", title: "Group Settings"))
options.append(group)
...
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return options.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let option = options[indexPath.row]!
let cell = tableView.dequeueReusableCellWithIdentifier(option.identifier, forIndexPath: indexPath)
(cell as! CellDescrptionConfigurable).cellDescription = option
(option as? ExpandCellInformer)?.delegate = self
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
guard let option = options[indexPath.row] else { return }
guard let expandableOption = option as? ExpandableOption else { return }
if expandableOption.identifier == "ExpandableCell" {
expandableOption.active = !expandableOption.active
}
}
func expandableCell(expandableCell: ExpandableCellDescriptor, didChangeActive active: Bool) {
guard let index = options.indexOf(expandableCell) else { return }
var indexPaths = [NSIndexPath]()
for row in 1..<expandableCell.countIfActive {
indexPaths.append(NSIndexPath(forRow: index + row, inSection: 0))
}
if active {
tableView.insertRowsAtIndexPaths(indexPaths, withRowAnimation: UITableViewRowAnimation.Fade)
} else {
tableView.deleteRowsAtIndexPaths(indexPaths, withRowAnimation: UITableViewRowAnimation.Fade)
}
}
这段代码看起来很长,但大部分只需要编写一次。用于正确绘制表格视图所需的大部分信息都存在于CellDescriptor.swift文件中,单元格配置代码存在于UITableViewCell子类中,而TableViewController本身的代码相对较少。
希望这能有所帮助。