从nib初始化自定义UITableViewCell而不使用dequeueReusableCellWithIdentifier

时间:2016-07-08 14:33:25

标签: ios swift

SWIFT

我需要制作一组细胞。我有几个自定义单元类(从UITableViewCell继承)和nib文件。

如何初始化单元格而不在tableview中注册nib并执行dequeueReusableCellWithIdentifier? 我是这样做的,但不要想,它会起作用:

var labelCell = CustomCellClass.initialize()

3 个答案:

答案 0 :(得分:1)

我在其他地方的评论中推断,你不希望单元格出列并重复使用的原因是你无法跟踪单元格中捕获的用户输入。

最重要的是,你真的应该允许细胞出列并重复使用,并恰好处理它。如果您在重复使用单元格时遇到问题,可以按照model-view-controller pattern

解决此问题

关键是当单元格中的值发生变化时,您的单元格应立即告诉视图控制器,以便视图控制器可以立即更新模型。然后,当视图控制器稍后需要使用与特定行关联的值执行某些操作时,它不会从单元格中检索它,而是从其自己的模型中检索它。

因此,我可以为单元格定义一个协议,以通知表格视图其文本字段已更改:

protocol CustomCellDelegate: class {
    func cell(cell: UITableViewCell, updatedCustomTextField textField: UITextField)
}

然后我会定义一个调用该委托的单元类:

class CustomCell: UITableViewCell {
    weak var delegate: CustomCellDelegate?

    @IBOutlet weak var customTextField: UITextField!          // hook up outlet to this property in IB

    @IBAction func didChangeValue(sender: UITextField) {      // hook up "editing changed" action for the text field to this method in IB
        delegate?.cell(self, updatedCustomTextField: sender)
    }
}

现在,视图控制器将:

  • 将重用的标识符注册到相关的NIB;
  • cellForRowAtIndexPath中,填充文本字段并将其自身指定为该单元格的委托;和
  • 如果用户更改任何内容,
  • 会处理updatedCustomTextField方法以更新模型。

因此,像:

class ViewController: UITableViewController, CustomCellDelegate {

    var values = ["One", "Two", "Three"]  // some initial values

    private let cellIdentifier = "CustomCell"

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.registerNib(UINib(nibName: "CustomCell", bundle: nil), forCellReuseIdentifier: cellIdentifier) // or use cell prototype with storyboard identifer specified
    }

    // MARK: UITableViewDataSource

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return values.count
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! CustomCell

        // populate cell and specify delegate

        cell.delegate = self
        cell.customTextField.text = values[indexPath.row]

        return cell
    }

    // MARK: CustomCellDelegate

    func cell(cell: UITableViewCell, updatedCustomTextField textField: UITextField) {
        // when the cell tells us that its text field's value changed, update our own model

        if let indexPath = tableView.indexPathForCell(cell), let string = textField.text {
            values[indexPath.row] = string
        }
    }
}

许多人可能倾向于通过将文本字段的IBAction直接挂钩到视图控制器方法来进一步简化此操作。这是有效的,并且不需要这个协议,但问题是你需要弄清楚这个特定的UIKit控件与哪一行相关联。常见的诀窍是向上导航视图层次结构以识别适当的单元格(例如,文本字段通常位于单元格内的内容视图中,因此您抓住textField.superview.superview as! UITableViewCell),但这对我来说感觉有点脆弱。

但不管这个细节如何,希望这能说明更广泛的模式。您应该让单元格(“视图”)立即更新控制器的任何数据更改,然后视图控制器立即更新模型,而不再需要让单元格跟踪用户输入,您不再需要担心iOS使用的单元重用优化。

答案 1 :(得分:0)

静态表的概念是它在IB中完全定义。一种解决方案是将这些细胞从其分离的NIB复制粘贴到含有该表的NIB中。

更好的解决方案是使表动态化,并使动态代码返回静态数量的节和行。将剩余的逻辑写成动态的(例如,注册所有的nib,并初始化一个单元标识符数组,如何在表中组织它们,使用该数组出列)。

答案 2 :(得分:0)

另一种解决方法:

1)View Controller中的UITextField委托。将值存储在数组

var textFieldValues = ["", "", "", "", "", "", "", "", "", ""] // with count of text fields in table. Init in top of ViewController.

//MARK:TextField Delegate

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    if string == " "
    {
        return false
    }

    let indexPathForCellWhereTextFieldIs = self.tableView.indexPathForCell(textField.superview?.superview as! UITableViewCell)
    textFieldValues[(indexPathForCellWhereTextFieldIs?.section)!] = (textField.text! as NSString).stringByReplacingCharactersInRange(range, withString: string) as NSString as String

    return true
}

2)在indexPathForRow

    cell.registrationTextField.text = textFieldValues[indexPath.section]
    cell.registrationTextField.delegate = self

3)从数组中获取数据

func tapOnRegisterButton(sender:UIButton)
{
    debugPrint(textFieldValues)
}