2016-10-26 1 views
0

저는 처음에 iOS 개발자였습니다. 지금은 꽤 오랫동안 문제에 봉착했습니다.(Swift) UITableView를 다시로드하여 UITextfield 입력을 기반으로 셀을 표시/숨기는 방법 (애니메이션)?

배경 : 저는 tableview가있는 단일 viewcontroller가 있습니다. 그것은 4 개의 동적 프로토 타입 셀을 가지고 있습니다 : prototypecell 1은 UITextField와 두 개의 레이블을 가지고 있고, prototypecell 2는 이미지를 가지고 있으며, prototypecell 3과 4는 하나의 레이블만을 가지고 있습니다. (참고 : 프로토 타입 셀 4는 객체의 배열을 기반으로하며 하나 이상의 셀을 가질 수 있습니다.)

화면을 열면 UITextField가있는 첫 번째 셀만 표시되어야합니다. 사용자가이 UITextField에 숫자 (최대 3 자릿수)를 입력하면 개체 배열의 기존 숫자인지 확인하기 위해 숫자를 비교해야합니다. 이 번호가 올바른지 입증되면 2 일이 일어날 것입니다 : 첫 번째 셀에

  1. 된 레이블 (... 색상, 글꼴, 크기) 레이아웃을 변경해야합니다. 그리고 첫 번째 셀은 rowHeight를 변경합니다.
  2. 다른 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! 
} 

어떤 도움이 될 것를 대단히 감사드립니다! 고맙습니다!

+0

는 왜 항상해야합니까 세 개의 세포를 사용할 수 있습니까? 추가 셀을 필요에 따라 삽입합니다 (numberOfRowsInSection이 항상 올바른 숫자를 반환하도록하십시오). – Paulw11

+0

@ Paulw11 화면에는 항상 최소 1 개의 셀 (inputCell)이 있지만 입력이 정확하면 추가 3 개의 셀이 추가됩니다. 프로토 타입 셀 2에는 1 행에 이미지가 있으면 프로토 타입 셀 3에 이름이있는 행 1 개가 있고 프로토 타입 셀 4에는 객체의 subArray를 기반으로 알 수없는 행이 있습니다. 그리고 이들 모두는 입력에 따라 높이를 변경할 수 있어야합니다. 따라서 numberOfRowsInSection은 1) 1 셀 (inputcell)과 2) 1 셀 (inputcell) + 2 (2 셀 모두 1 행을 가짐) + 객체의 하위 배열을 기반으로 한 숫자로 바뀔 것입니다. 어떻게 동적으로 전환 할 수 있습니까? 이들? – Aovib

답변

0

작업이 완료되면 (입력이 원하는대로 일치하는지 확인), tableview에 사용중인 데이터 소스를 채 웁니다 (데이터 소스로 사용할 객체의 빈 배열을 선언해야합니다. this), reloadData()를 tableview에 사용하십시오.

당신의 세포의 높이를 들어

, 당신은 tableView.rowHeight = UITableViewAutomaticDimension (https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/AutolayoutPG/WorkingwithSelf-SizingTableViewCells.html)

관련 문제