저는 처음에 iOS 개발자였습니다. 지금은 꽤 오랫동안 문제에 봉착했습니다.(Swift) UITableView를 다시로드하여 UITextfield 입력을 기반으로 셀을 표시/숨기는 방법 (애니메이션)?
배경 : 저는 tableview가있는 단일 viewcontroller가 있습니다. 그것은 4 개의 동적 프로토 타입 셀을 가지고 있습니다 : prototypecell 1은 UITextField와 두 개의 레이블을 가지고 있고, prototypecell 2는 이미지를 가지고 있으며, prototypecell 3과 4는 하나의 레이블만을 가지고 있습니다. (참고 : 프로토 타입 셀 4는 객체의 배열을 기반으로하며 하나 이상의 셀을 가질 수 있습니다.)
화면을 열면 UITextField가있는 첫 번째 셀만 표시되어야합니다. 사용자가이 UITextField에 숫자 (최대 3 자릿수)를 입력하면 개체 배열의 기존 숫자인지 확인하기 위해 숫자를 비교해야합니다. 이 번호가 올바른지 입증되면 2 일이 일어날 것입니다 : 첫 번째 셀에
- 된 레이블 (... 색상, 글꼴, 크기) 레이아웃을 변경해야합니다. 그리고 첫 번째 셀은 rowHeight를 변경합니다.
- 다른 3 개의 셀이 나타나야하며 번호에 해당하는 데이터가 표시되어야합니다.
숫자가 잘못된 경우 추가 셀이 나타나지 않고 첫 번째 셀이 업데이트되어 사용자에게 잘못되었음을 알립니다.
문제점 : 첫 번째 셀의 숫자 입력에 따라 3 개의 셀이 나타나고 사라지는 방식에 애니메이션을 적용하는 데 문제가 있습니다. 보다 구체적으로는 "toggleCellsVisibility"메소드와 셀 생성과 관련된 메소드입니다.
beginUpdates(), endUpdates(), reloadData(), reloadRowsAtIndexPath(), DispatchQueue.main.async {} 및 UIView.Animate()의 여러 조합을 시도했습니다. 그러나 내 코드가 작동하는 유일한 방법은 아래와 같이 toggleCellsVisibility 메서드를 구현하면 어떤 애니메이션 옵션도 제공하지 않는다는 것입니다.
데이터 작성 및 다시로드에 문제가있는 것으로 보입니다. 이것은 글로벌 변수 indexOfObject와 tempObject의 사용과 관련이 있다고 생각합니다.이 변수는 화면이로드 될 때 더미 데이터를 보유하고 올바른 숫자가 주어지면 실제 데이터로 표시되고 무시됩니다.
요약 : 첫 번째 셀에 정확한 숫자가 입력되면 3 개의 셀을 삽입/생성하고 특정 설정으로이 변경 사항에 애니메이션을 적용 할 수 있습니까?
추가 : heightForRowAtIndexPath를 사용하지 않고 여분의 셀을 표시하거나 숨길 수 있습니까? 세포가 자체 크기가 될 수 있다면 더 좋을 것입니다.
내가 선택한 코드의 관련 부분 단순화 :1)의 TableView 클래스 :
class TableViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, updateUITableView {
var objects: [Object] = [
name: "test1", number: "test2", image: "imageName1", color: UIColor.black, array: ["test3", "test4"],
[name: "test1", number: "test2", image: "imageName2", color: UIColor.white, array: ["test3", "test4", "test5"]
//...
]
var cellsRowHeight = false
var indexOfObject: Int = 0
var tempObject = Object[name: "test1", number: "test2", color: UIColor.blue, image: "imageName3", array: ["test3"]]
@IBOutlet var tableView: UITableView!
// MARK: - Table view data source
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let numberOfRows = 3 + tempObject.subArray.count
return numberOfRows
}
//START - Input received from textfield in first cell
func checkNumberInput(senderCell: SearchInputTableViewCell, number: String) {
// step 1: Check if number exists
let match = checkNumberMatch(numberInput: number)
// step 2: Change lay-out of input cell
senderCell.changeLayout(numberMatch: match.0, name: match.1?.name, color: match.1?.color)
// step 3: Show/hide cells
toggleCellsVisibility(numberMatch: match.0)
}
//STEP 1: Check if the number corresponds to an existing number
func checkNumberMatch(numberInput: String) -> (Bool, Object?) {
var returnObject: Object?
var tuple = (false, returnObject)
for (index, object) in objects.enumerated() where object.number == numberInput {
returnObject = object
tuple = (true, returnObject)
tempObject = object
indexOfObject = index
}
return tuple
}
//STEP 3 = !!PROBLEM!!
func toggleCellsVisibility(numberMatch: Bool) {
cellsRowHeight = numberMatch
// if/else because of additional future implementation
if numberMatch == true { //Cells appear
DispatchQueue.main.async {
self.tableView?.reloadData()
}
} else { //Cells disappear
DispatchQueue.main.async {
self.tableView?.reloadData()
}
}
}
//STEP 4:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
switch (indexPath.row) {
case 0 where !cellsRowHeight:
return 187
case 0 where cellsRowHeight:
return 170
case 1 where !cellsRowHeight:
return 0
case 1 where cellsRowHeight:
return 170
case 2 where !cellsRowHeight:
return 0
case 2 where cellsRowHeight:
return 54
case 3...200 where !cellsRowHeight:
return 0
case 3...200 where cellsRowHeight:
return 44
default:
return 44
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let cellIdentifier = "InputCell"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! InputCell
cell.delegate = self
return cell
}
else if indexPath.row == 1 {
let cellIdentifier = "Cell2"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! Cell2
cell.image?.image = UIImage(named: objects[indexOfObject].image)
return cell
}
else if indexPath.row == 2 {
let cellIdentifier = "Cell3"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! Cell3
cell.name?.text = objects[indexOfObject].name
return cell
}
else {
let cellIdentifier = "Cell4"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! Cell4
cell.name?.text = objects[indexOfObject].subArray[(indexPath as IndexPath).row - 3]
return cell
}
}}
2) 세포 등급 :이
protocol updateUITableView: class {
func checkNumberInput(senderCell: SearchInputTableViewCell, number: String)
}
class InputCell: UITableViewCell, UITextFieldDelegate {
var delegate: updateUITableView?
@IBOutlet var textField: UITextField!
@IBOutlet var nameLabel: UILabel!
//... and other labels
func changeLayout(numberMatch: Bool, name: String?, color: UIColor?) {
if numberMatch == true {
//lay-out changes to labels
}
else {
//lay-out changes to labels
}
}
//Set maximum character limit in textField and dismiss keyboard when character limit (3) is reached.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let currentCharacterCount = textField.text?.characters.count ?? 0
let newLength = currentCharacterCount + string.characters.count - range.length
if (newLength == 3) {
textField.text = (textField.text! as NSString).replacingCharacters(in: range, with: string)
//Get text from textField
let numberInput: String? = textField.text! //Get number if 3 characters entered
if numberInput != nil {
delegate?.checkNumberInput(senderCell: self, number: numberInput!)
}
textField.resignFirstResponder()
if (range.length + range.location > currentCharacterCount) {
return false
} else {
return true
}
}
return true
}
}
class Cell2: UITableViewCell {
@IBOutlet var image: UIImageView!
}
class Cell3: UITableViewCell {
@IBOutlet var name: UILabel!
}
class Cell4: UITableViewCell {
@IBOutlet var name: UILabel!
}
어떤 도움이 될 것를 대단히 감사드립니다! 고맙습니다!
는 왜 항상해야합니까 세 개의 세포를 사용할 수 있습니까? 추가 셀을 필요에 따라 삽입합니다 (numberOfRowsInSection이 항상 올바른 숫자를 반환하도록하십시오). – Paulw11
@ Paulw11 화면에는 항상 최소 1 개의 셀 (inputCell)이 있지만 입력이 정확하면 추가 3 개의 셀이 추가됩니다. 프로토 타입 셀 2에는 1 행에 이미지가 있으면 프로토 타입 셀 3에 이름이있는 행 1 개가 있고 프로토 타입 셀 4에는 객체의 subArray를 기반으로 알 수없는 행이 있습니다. 그리고 이들 모두는 입력에 따라 높이를 변경할 수 있어야합니다. 따라서 numberOfRowsInSection은 1) 1 셀 (inputcell)과 2) 1 셀 (inputcell) + 2 (2 셀 모두 1 행을 가짐) + 객체의 하위 배열을 기반으로 한 숫자로 바뀔 것입니다. 어떻게 동적으로 전환 할 수 있습니까? 이들? – Aovib