【发布时间】:2016-10-28 14:22:30
【问题描述】:
背景:单个 ViewController 包含 4 个自定义原型单元。第一个始终可见,并具有UITextField。
原型单元 2、3 和 4 分别包含图像、标签和标签。但是,原型单元 4 是基于数组的,可以有 1 行或多行,具体取决于第一个单元中的输入。
当在第一个单元格中输入某个字符串时,会检查是否存在一个对象,该对象的某个属性中包含该字符串。如果该值不正确,则第一个单元格会更改高度和布局。如果值正确,第一个单元格会改变高度,最重要的是其他 3 个原型单元格会展开以显示对应于字符串输入的对象的详细信息。如果用户随后输入了另一个不正确的字符串,则单元格会崩溃。
问题: 为其他 3 个单元格的展开/折叠设置动画。我无法弄清楚如何在 beginUpdates() 和 endUpdates() 之间定义 numberOfRowsInSection() 方法和代码块(下面我的代码中的第 2 步)。即使没有 arraycells 实现,在 insertRows() 之后调用 reloadRows() 似乎也不起作用。
我尝试了什么:
- reloadData() = 正确显示数据,但我不能使用它,因为它不会提供必要的动画。
- beginUpdates() 和 endUpdates() 之间没有任何内容 = 给出以下错误:
无效更新:第 0 节中的行数无效。更新后现有节中包含的行数 (6) 必须等于更新前该节中包含的行数 (1),加上或减去从该节插入或删除的行数(0 插入,0 删除)加上或减去移入或移出该节的行数(0 移入,0 移出)。'
我相信这与最后一个原型单元格基于数组的事实有关,我没有重新加载单元格的实际数据,只是视图。
- 与 insertRowsAtIndexPath、reloadRowsAtIndexPath、...的其他组合 = 给出与行数相关的类似错误。
任何帮助将不胜感激!
简化代码:
class TableViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, updateUITableView {
var people: [Person] = [
Person(name: "name", image: "imagename1", description: "description1", children: ["name1","name2","name3"]),
Person(name: "name2", image: "imagename3", description: "description2", children: ["name4", "name5", "name6"])
]
enum Flag {
case start
case match
case noMatch
}
var flag = Flag.start
var globalObject: Person?
@IBOutlet var tableView: UITableView!
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch (flag) {
case .start :
return 1
case .noMatch:
return 1
case .match:
return 3 + (globalObject?.children.count)! //PROBLEM!
}
}
//START - Input received from tableViewCell
func checkName(senderCell: SearchInputTableViewCell, name: String) {
// STEP 1: Check if person exists
let person = checkPersonNameMatch(nameInput: name)
globalObject = person //save globally for cellForRowsAtIndexPath
// STEP 2: Show/hide cells
toggleCellsVisibility(person: person)
}
//STEP 1:
func checkPersonNameMatch(nameInput: String) -> Person? {
guard let index = people.index(where: {$0.name == nameInput}) else {
flag = .noMatch
return nil
}
let personFound = people[index]
flag = .match
globalObject = personFound
return personFound
}
//STEP 2 = PROBLEM!
func toggleCellsVisibility(person: Person?) {
if person != nil { //Cells appear
UIView.animate(withDuration: 0.7, animations: {
self.tableView.beginUpdates()
let indexPath: IndexPath = IndexPath(row: 1, section: 0) //for Image cell
let indexPath2: IndexPath = IndexPath(row: 2, section: 0) //for Description cell
//let indexPath3: IndexPath = IndexPath[....] //for array in Children cell
self.tableView.insertRows(at: [indexPath], with: .bottom)
self.tableView.insertRows(at: [indexPath2], with: .bottom)
self.tableView.reloadRows(at: [indexPath], with: .bottom)
self.tableView.reloadRows(at: [indexPath2], with: .bottom)
//... a for-loop to reload the array cells here?
self.tableView.endUpdates()
})
} else { //Cells disappear
UIView.animate(withDuration: 0.4, animations: {
self.tableView.beginUpdates()
//... same code as above?
self.tableView.endUpdates()
})
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch indexPath.row {
case 0:
let cellIdentifier = "InputCell"
let inputCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! InputTableViewCell
inputCell.delegate = self
switch (flag) {
case .start:
self.tableView.rowHeight = 187
case .match:
self.tableView.rowHeight = 170
case .noMatch:
self.tableView.rowHeight = 200
}
return inputCell
case 1:
let cellIdentifier = "ImageCell"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! ImageTableViewCell
cell.image?.image = UIImage(named: (globalObject?.image)!)
switch (flag) {
case .start:
self.tableView.rowHeight = 0
case .match:
self.tableView.rowHeight = 170
case .noMatch:
self.tableView.rowHeight = 0
}
return cell
case 2:
let cellIdentifier = "DescriptionCell"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! DescriptionTableViewCell
cell.description?.text = globalObject?.description
switch (flag) {
case .start:
self.tableView.rowHeight = 0
case .match:
self.tableView.rowHeight = 54
case .noMatch:
self.tableView.rowHeight = 0
}
return cell
default:
let cellIdentifier = "ChildrenCell"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! ChildrenTableViewCell
cell.childName?.text = globalObject?.children[(indexPath as IndexPath).row - 3]
switch (flag) {
case .start:
self.tableView.rowHeight = 0
case .match:
self.tableView.rowHeight = 44
case .noMatch:
self.tableView.rowHeight = 0
}
return cell
}
}
}
【问题讨论】:
标签: ios swift uitableview reloaddata