배경 : 단일 ViewController에는 4 개의 사용자 정의 프로토 타입 셀이 있습니다. 첫 번째 것은 항상 표시되며 UITextField
입니다. 프로토 타입 셀 2, 3 및 4에는 이미지, 레이블 및 레이블이 각각 들어 있습니다. 그러나 프로토 타입 셀 4는 배열을 기반으로하며 첫 번째 셀의 입력에 따라 1 또는 여러 행을 가질 수 있습니다.begin-endUpdates() 및 여러 사용자 정의 셀을 사용하여 UITableViewCells를 확장/축소하는 방법은 무엇입니까?
첫 번째 셀에 특정 문자열을 입력하면 해당 문자열이있는 속성이 속성에 있는지 확인하는 검사가 수행됩니다. 값이 인 경우 일 경우 첫 번째 셀의 높이와 레이아웃이 변경됩니다. 값이 인 경우이면 첫 번째 셀의 높이가 변경되고 가장 중요한 것은 3 개의 다른 프로토 타입 셀이 확장되어 String 입력에 해당하는 객체의 세부 정보를 표시합니다. 그런 다음 사용자가 잘못된 다른 문자열을 입력하면 셀이 축소됩니다.
문제점 : 다른 세 개의 셀을 확장하거나 축소하는 애니메이션입니다. beginOpdates()와 endUpdates() 사이에서 numberOfRowsInSection() 메서드와 코드 블록 (아래 코드 2 단계)을 정의하는 방법을 파악하는 데 문제가 있습니다. 심지어 arraycells 구현없이 insertRows() 후에 reloadRows()를 호출하는 것은 효과가없는 것 같습니다. 내가 뭘하려
:
- reloadData는() = 데이터를 올바르게 보여 주지만, 필요한 애니메이션을 제공하지 않기 때문에 나는 그것을 사용할 수 없습니다.
- beginUpdates()와 = 다음과 같은 오류주는 사이에서 아무것도없이 EndUpdates 사이() :이가 마지막 프로토 타입 셀이 배열에 따라 나는 '는 사실과 관련이 생각
Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (6) must be equal to the number of rows contained in that section before the update (1), plus or minus the number of rows inserted or deleted from that section (0 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
을 셀의 실제 데이터를 다시로드하지 않고보기 만합니다.
- 다른 조합은 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
}
}
}
자세한 내용은 내 대답은 여기를 참조하십시오 : http://stackoverflow.com/a/40198962/341994 – matt
나는 그 접근 방식을 시도했지만 그것은 나에게 '잘못된 행 수의 오류가 위에서 설명한 바와 같이했다. 내 상황과 내가 링크 한 상황의 차이는 내 데이터의 종속성입니다. 표시/확장되는 셀의 데이터 (및 번호)는 첫 번째 셀의 입력을 기반으로합니다. 따라서 처음에 어떻게 정의 할 수 있는지 미리 알지 못합니다. 사전에 얼마나 많은 데이터가있을 것이며 어떤 데이터가 포함될 지 미리 알지 못합니다. – Aovib
"얼마나 많은 데이터가있을 것이며 어떤 데이터가 포함될 것인지 미리 알지 못하면"좋습니다. 그러나'beginUpdates'를 호출하기 전에 항상 _model_를 업데이트해야합니다. 기본적으로 이것은 행을 추가 할 때와 다릅니다. 그리고 귀하의 경우, 내가 말할 수있는 한, _row_ 삽입을 할 필요가 없습니다. – matt