我正在使用this post中提到的技术的变体来动态添加和删除表格视图单元格。
最初,表格视图单元格如下所示:
然后,我在第1部分添加了一个新单元格。第1部分是“结果”部分上方的部分。所以我希望新单元格出现在名为“h”的单元格下方。但不是!它变成了这个!
新细胞添加在第2部分(“结果”部分)中,并添加到名为“b”的细胞下方。更令人惊讶的是,第2节中的第二个单元格已经消失了!
以下是我添加单元格的方法:
我在这里有一组单元格:
var cells: [[UITableViewCell]] = [[], [], []]
数组中的每个子数组表示一个部分。在viewDidLoad
中,我通过调用:
addCellToSection(1, cell: someCell)
addCellToSection
定义为
func addCellToSection(section: Int, cell: UITableViewCell) {
cells[section].append(cell)
tableView.insertRowsAtIndexPaths([NSIndexPath(forRow: cells[section].endIndex - 1, inSection: section)], withRowAnimation: .Top)
}
表视图数据源方法的定义方式与上述帖子相同。
我在添加单元格时尝试打印每个部分中的单元格数量:
print("no. of rows in section 1: \(self.tableView(tableView, numberOfRowsInSection: 1))")
print("no. of rows in section 2: \(self.tableView(tableView, numberOfRowsInSection: 2))")
打印的值是一致的,即当我添加一个新的单元格时,没有。行增加1.但奇怪的是它一直将行放在错误的位置。
额外信息:我如何创建单元格:
我首先从原型细胞中取出细胞。然后,我致电viewWithTag
以获取单元格中的文本字段,并将其添加到[(UITextField, UITextField)]
。不知道这是否重要。
答案 0 :(得分:1)
好的,首先,你应该从不在一些自定义集合中存储UITableView单元格。这是并且应该由iOS完成,而不是你。
用于填充单元格的数据存储在我认为的某个模型中?
您的tableView应使用以下任一方式注册单元格:
func registerClass(cellClass: AnyClass?, forCellReuseIdentifier identifier: String)
或
func registerNib(nib: UINib?, forCellReuseIdentifier identifier: String)
或在Xib / Storyboard中使用Prototype单元格。
我推荐此设置或类似设置:
class MyModel {
/* holds data displayed in cell */
var name: String?
var formula: String?
init(name: String, formula: String) {
self.name = name
self.formula = formula
}
}
class MyCustomCell: UITableViewCell, UITextFieldDelegate {
static var nibName = "MyCustomCell"
@IBOutlet weak var nameTextField: UITextField!
@IBOutlet weak var formulaTextField: UITextField!
weak var model: MyModel?
override func awakeFromNib() {
super.awakeFromNib()
nameTextField.delegate = self
formulaTextField.delegate = self
}
func updateWithModel(model: MyModel) {
/* update labels, images etc in this cell with data from model */
nameTextField.text = model.name
formulaTextField.text = model.formula
self.model = model
}
/* This code only works if MyModel is a class, because classes uses reference type, and the value
of the name and formula properies are changed in the model stored in the dictionary */
func textFieldShouldEndEditing(textField: UITextField) -> Bool {
let newText = textField.text
switch textField {
case nameTextField:
model?.name = newText
case formulaTextField:
model?.formula = newText
default:
print("Needed by compiler..")
}
}
}
class MyController: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var tableVieW: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
/* This is not needed if you are using prototype cells in the Xib or Storyboard.
Convenient to use nib name as cell identifier */
tableVieW.registerNib(UINib(nibName: MyCustomCell.nibName, bundle: nil), forCellReuseIdentifier: MyCustomCell.nibName)
tableVieW.delegate = self
tableVieW.dataSource = self
}
private var dictionaryWithModelsForSection: Dictionary<Int, [MyModel]>!
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
let sectionCount = dictionaryWithModelsForSection.keys.count
return sectionCount
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
guard let models: [MyModel] = modelsForSection(section) else {
return 0
}
let rowCount = models.count
return rowCount
}
private func modelsForSection(section: Int) -> [MyModel]? {
guard section < dictionaryWithModelsForSection.count else {
return nil
}
let models = dictionaryWithModelsForSection[section]
return models
}
private func modelAtIndexPath(indexPath: NSIndexPath) -> MyModel? {
guard let models = modelsForSection(indexPath.section) where models.count > indexPath.row else {
return nil
}
let model = models[indexPath.row]
return model
}
func addRowAtIndexPath(indexPath: NSIndexPath, withModel model: MyModel) {
add(model: model, atIndexPath: indexPath)
tableVieW.insertRowsAtIndexPaths([indexPath], withRowAnimation: .None)
}
private func add(model model: MyModel, atIndexPath indexPath: NSIndexPath) {
guard var models = modelsForSection(indexPath.section) where indexPath.row <= models.count else { return }
models.insert(model, atIndex: indexPath.row)
dictionaryWithModelsForSection[indexPath.section] = models
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(MyCustomCell.nibName, forIndexPath: indexPath)
return cell
}
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
guard let
cell = cell as? MyCustomCell,
model = modelAtIndexPath(indexPath) else { return }
cell.updateWithModel(model)
}
}
如果你想插入一个单元格,你可以使用我在上面的MyController中编写的方法addRowAtIndexPath:withModel
,你需要从某个函数调用它来创建相应的模型......