(快速)如何通过重新加载UITableView基于UITextfield输入显示/隐藏单元格? [英] (Swift) How to (animate) show/hide cells based on UITextfield input by reloading a UITableView?

查看:98
本文介绍了(快速)如何通过重新加载UITableView基于UITextfield输入显示/隐藏单元格?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是一名开始的iOS开发人员,并且在一个问题上已经停留了很长时间。

I'm a beginning iOS developer and I've been stuck on an issue for quite some time now.

背景知识:有一个带有tableview的viewcontroller。它包含4个动态原型单元:prototypecell 1具有UITextField和几个标签,prototypecell 2具有图像,prototypecell 3和4仅具有单个标签。 (注意:原型单元格4基于对象中的数组,并且可以具有1个或多个单元格)。

Background: I have a single viewcontroller with a tableview. It holds 4 dynamic prototype cells: prototypecell 1 has an UITextField and a couple of labels, prototypecell 2 has an image, prototypecell 3 and 4 only have a single label. (Note: prototype cell 4 is based on an array in the object and can have 1 or more cells)

打开屏幕后,只有第一个带有UITextField的单元格才应该可见。当用户在此UITextField中输入数字(最多3个数字)时,必须比较该数字以检查它是否是对象数组中的现有数字。如果该数字正确,则必须进行两件事:

Upon opening the screen, only the first cell with the UITextField should be visible. When an user enters a number (max. 3 digits) in this UITextField, the number has to be compared to check if it is an existing number in an array of objects. If this number proves correct, 2 things will have to happen:


  1. 第一个单元格中的标签将需要更改布局(颜色,
    字体,大小...)。并且第一个单元格更改rowHeight。

  2. 其他三个单元格必须出现并显示与该数字相对应的数据。

如果数字错误,则不会出现多余的单元格,并且第一个单元格会更新以告知用户它是错误的。

If the number is wrong, no extra cells appear and the first cell updates to tell the user it was incorrect.

问题:我在根据第一个单元格中的数字输入来动画化3个单元格的出现和消失方式时遇到问题。更具体地讲,方法 toggleCellsVisibility及其与单元格创建的关系。

Problem: I'm having issues with animating the way the 3 cells appear and disappear based on the numberinput in the first cell. More specifically the method "toggleCellsVisibility" and how it relates to the creation of the cells.

我尝试了以下多种组合:beginUpdates(),endUpdates(),reloadData() ,reloadRowsAtIndexPath(),DispatchQueue.main.async {}和UIView.Animate()。但是,我的代码唯一可行的方法是实现以下所示的toggleCellsVisibility方法,该方法不会为我提供任何动画选项。

I tried multiple combinations of: beginUpdates(), endUpdates(), reloadData(), reloadRowsAtIndexPath(), DispatchQueue.main.async {} and UIView.Animate(). But the only way my code works is if I implement the toggleCellsVisibility method as below, which does not give me any animation options.

我似乎在做错了创建和重新加载数据。我认为这与全局变量indexOfObject和tempObject的使用有关,它们在加载屏幕时保存虚拟数据,然后在给出正确数字后显示并被实际数据覆盖。

I seem to be doing something wrong with the creation and reloading of the data. I think this is related to the use of the global variables indexOfObject and tempObject which hold dummy data when the screen is loaded, and are then shown and overridden with the actual data when a correct number is given.

摘要::如果在第一个单元格中输入了正确的数字,我是否能以某种方式插入/创建3个单元格,同时还可以通过此特定设置设置动画效果?

Summary: Could I somehow insert/create the 3 cells when a correct number is inputted in the first cell, while also animating this change with this particular setup?

其他:
是否可以通过不使用heightForRowAtIndexPath来显示/隐藏额外的单元格?

Additional: Can I show/hide the extra cells by not using the heightForRowAtIndexPath? It would be better if the cells could self-size.

我选择并简化了相关代码段:

I selected and simplified the relevant pieces of code:

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!
}

任何帮助将不胜感激!谢谢!

Any help would be immensely appreciated! Thank you!

推荐答案

完成操作(检查输入是否符合您的要求)后,填充您要使用的数据源重新用于表视图(应该声明要用作数据源的对象的空数组,并使用它),然后在表视图上使用reloadData()。

When your action is done (checking that the input match whatever you want), populate the data source you're using for your tableview (you should declare an empty array of objects you want to use as a datasource, and use this), then use reloadData() on your tableview.

对于单元格的高度,可以使用 tableView.rowHeight = UITableViewAutomaticDimension https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/AutolayoutPG/WorkingwithSelf-SizingTableViewCells.html

For the height of your cells, you can use tableView.rowHeight = UITableViewAutomaticDimension (https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/AutolayoutPG/WorkingwithSelf-SizingTableViewCells.html)

这篇关于(快速)如何通过重新加载UITableView基于UITextfield输入显示/隐藏单元格?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆