Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/93.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 从nib初始化自定义UITableViewCell,不带dequeueReusableCellWithIdentifier_Ios_Swift - Fatal编程技术网

Ios 从nib初始化自定义UITableViewCell,不带dequeueReusableCellWithIdentifier

Ios 从nib初始化自定义UITableViewCell,不带dequeueReusableCellWithIdentifier,ios,swift,Ios,Swift,SWIFT 我需要做一个细胞阵列。我有几个带有nib文件的自定义单元格类(继承自UITableViewCell) 如何在不在tableview中注册nib的情况下初始化单元,并使用Identifier执行dequeueReusableCellWithIdentifier? 我是这样做的,但不要认为它会起作用: var labelCell = CustomCellClass.initialize() 静态表的基本思想是它在IB中完全定义。一种解决方案是将这些单元格从其孤立的NIB复制粘贴到包含该

SWIFT

我需要做一个细胞阵列。我有几个带有nib文件的自定义单元格类(继承自UITableViewCell)

如何在不在tableview中注册nib的情况下初始化单元,并使用Identifier执行dequeueReusableCellWithIdentifier? 我是这样做的,但不要认为它会起作用:

var labelCell = CustomCellClass.initialize()

静态表的基本思想是它在IB中完全定义。一种解决方案是将这些单元格从其孤立的NIB复制粘贴到包含该表的NIB


更好的解决方案是使表成为动态的,并让动态代码返回静态数量的节和行。将逻辑的其余部分视为动态写入(例如,注册所有NIB,并初始化单元标识符数组,以表中的组织方式,使用该数组出列).

我从其他地方评论中的讨论推断,您不允许单元格出列和重复使用的原因是您无法跟踪单元格中捕获的用户输入

底线是,您真的应该允许这些单元出列和重用,并适当地处理它们。如果在重复使用单元格时遇到问题,可以通过将“模型”(即数据)与“视图”(即UIKit控件)分离来解决。这是的精神,但在任何关注点分离的模式(例如MVVP、MVP等)中都是如此

关键是当单元格中的值更改时,单元格应立即通知视图控制器,以便视图控制器可以立即更新模型。然后,当视图控制器稍后需要对与特定行关联的值执行某些操作时,它不会从单元格中检索该值,而是从自己的模型中检索该值

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

protocol CustomCellDelegate: class {
    func cell(_ cell: CustomCell, didUpdateTextField 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, didUpdateTextField: sender)
    }
}
现在,视图控制器将:

  • 向相关NIB注册重用标识符
  • cellForRowAt
    中,填充文本字段并将其自身指定为该单元格的委托;及
  • 处理
    didUpdateTextField
    方法以在用户更改任何内容时更新模型
因此,类似于:

class ViewController: UITableViewController {

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

    private let cellIdentifier = "CustomCell"

    override func viewDidLoad() {
        super.viewDidLoad()

        // if you’re using NIBs, you register them. 
        // obviously if using prototype cells in your storyboard, this isn’t necessary.

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

// MARK: - UITableViewDataSource

extension ViewController {

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

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! CustomCell

        // populate cell and specify delegate

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

        return cell
    }
}

// MARK: - CustomCellDelegate

extension ViewController: CustomCellDelegate {
    func cell(_ cell: CustomCell, didUpdateTextField textField: UITextField) {
        // when the cell tells us that its text field's value changed, update our own model

        if let indexPath = tableView.indexPath(for: cell), let string = textField.text {
            values[indexPath.row] = string
        }
    }
}
许多人可能倾向于通过将文本字段的
iAction
直接挂接到视图控制器方法来进一步简化此操作。这是可行的,并且消除了对该协议的需要,但问题是您需要确定该特定UIKit控件与哪一行相关联。常见的技巧是在视图层次结构中向上导航以识别适当的单元格(例如,文本字段通常位于单元格内的内容视图中,因此您可以抓取
textField.superview.superview as!UITableViewCell
),但我觉得这有点脆弱

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


有关Swift 2格式副本,请参阅。

另一种解决方法:

1) 视图控制器中的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)
}

为什么“没有注册nib”和为什么“没有dequeueReusableCellWithIdentifier”?这在这个问题上并不重要。但是如果你只是为了兴趣而想知道的话——制作一个静态表。我需要它从放置在我单元格中的文本字段、分段控件和切换器中获取值。您可以使用
loadNibNamed:owner:options:
方法对
NSBundle
tableview进行静态处理。只有DAN回答这个问题?)问题是,当我想从单元格获取一些值时,已退出队列的-它们为零。只有当所有单元格都显示在屏幕上时,您的解决方案才会起作用。您能进一步解释吗?从单元格中获取值是一个常见的错误。只给单元格赋值。这些值保存在一个模型中(也称为数据源)。如果我发现如何从模型中获取数据(而不是从单元格中获取数据,因为单元格在屏幕边界后变为nill),那将非常好。下一步我将cell=self.tableView.cellforrowatinexpath(nsindepath.init(forRow:0,instation:NKVPhoneField))设置为?NKVTextFieldTableVCell然后从单元格
中获取值打印(cell?.registrationTextField.text)
我明白了。如果单元格包含文本字段,则必须使视图控制器成为该文本字段的委托,并且在编辑该文本字段时,该委托必须在模型中记录该字段中的文本。请参见此处的答案(答案中的“可选”部分):-)您将只给单元格赋值。暂时忘掉表格视图。创建一个表示用户将看到的对象的数组。控制器的工作是从该数组(并且仅从该数组)中提供和获取值。它的另一项工作是重新加载表视图并配置单元格(当CellForRowatineXpath请求时)以匹配该数组中的内容。在tableview编程和MVC中,这是一个非常重要的思想。