我在视图控制器中也有一个TableView
,在UILabel
中也有一个UIViewController
。一切都能很好地显示,但是我正在努力实现某些目标,而我无法简单地将其背后的逻辑。
tableview单元格具有一个UILabel,该单元格上具有Int
值,这些数字现在变化了,如何在tableView单元格中获取Label上的数字总和并显示在视图控制器中的Label上。
我尝试在UIView控制器中创建一个变量并将此值添加到t,但由于无法将这个数字加在一起而无法执行操作
有关如何执行此操作的任何帮助。谢谢
var total: Double?
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch indexPath.section {
case 0:
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! BrokageCheckoutCell
cell.configure()
total = Double("\(cell.subPrice.text!)")
cell.selectionStyle = .none
return cell
case 1:
let cell = tableView.dequeueReusableCell(withIdentifier: cellId2, for: indexPath) as! OtherCheckoutCell
cell.configure()
cell.selectionStyle = .none
return cell
default: break
}
return UITableViewCell()
}
答案 0 :(得分:1)
您问:
如何获取tableView单元格中Label上的数字总和并显示在视图控制器中的Label上
简而言之,您没有。表格视图单元格中的标签(属于“视图”的一部分)不是我们的数据源。它仅用于显示各个字符串。
例如,假设您的应用程序要累加100个项目,但该应用程序的表格视图一次只能显示12行。为了提高内存和性能,iOS将重用滚动到视图外的单元格,以显示滚动到视图中的新行的内容。但这意味着您不能说“将这100个单元格中所有标签的内容相加”,因为没有100个单元格;只有十二个。
您的应用应改为引用其“模型”,即cellForRowAt
用于确定在给定的表格视图单元格中显示什么的结构(例如,数组)。因此,如果要累加总数,则应累加该数组中的值,而不要完全引用单元格。
并且如果您的单元格具有允许修改数据的控件,则该单元格应启动模型的更新。然后,计算总计(对数组中的值求和)的过程仍然有效。
因此,我们来看一个示例:
您应该有一个包含要求和的数字的模型。您的示例尚不清楚,因此我将创建一个示例,其中每个表行均包含名称,单价和数量:
struct Item {
let name: String
let unitPrice: Decimal
var quantity: Decimal
}
在此示例中,任何给定行的总计将是数量乘以单价。所有行的总计将是所有这些乘积的总和。
然后,您的视图控制器可能会有一个用于其模型的数组:
var items: [Item] = ...
然后,当您要更新总计标签时,只需一种方法即可计算出每一行总计的数量乘以总计价格,然后对这些值求和以计算总计。然后它将相应地更新总计文本字段:
private extension ViewController {
func updateTotal() {
let total = items
.map { $0.quantity * $0.unitPrice }
.reduce(0, +)
totalLabel.text = totalFormatter.string(for: total)
}
}
注意,我不是从单元格中检索这些数字(因为这些数字可能会被重复使用),而是从模型中检索所有我需要的数据。
但是,这里的关键是,例如,如果您的单元格允许用户更改这些值之一,则需要一种机制来更新表视图控制器的模型。我们将为此使用协议:
protocol ItemCellDelegate: class {
func cell(_ cell: ItemCell, didUpdateQuantity quantity: Decimal)
}
class ItemCell: UITableViewCell {
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var quantityTextField: UITextField!
@IBOutlet weak var unitPriceLabel: UILabel!
static let quantityFormatter: NumberFormatter = ...
static let priceFormatter: NumberFormatter = ...
weak var delegate: ItemCellDelegate?
}
很明显,当您配置单元格时,视图控制器将指定用于更新文本字段(或其他内容)的委托:
// MARK: Public methods
extension ItemCell {
func configure(name: String, quantity: Decimal, unitPrice: Decimal, delegate: ItemCellDelegate) {
self.delegate = delegate
nameLabel.text = name
quantityTextField.text = ItemCell.quantityFormatter.string(for: quantity)
unitPriceLabel.text = ItemCell.priceFormatter.string(for: unitPrice)
}
}
ItemCell
得到更新时,它仅调用委托:
// MARK: Private methods
private extension ItemCell {
@IBAction func didUpdateQuantity(_ sender: UITextField) {
var quantity: Decimal?
if let text = sender.text, let value = ItemCell.quantityFormatter.number(from: text) {
quantity = value.decimalValue
}
delegate?.cell(self, didUpdateQuantity: quantity ?? 0)
}
}
然后,当视图控制器配置单元格时,它将提供自己作为委托:
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ItemCell", for: indexPath) as! ItemCell
let item = items[indexPath.row]
cell.configure(name: item.name, quantity: item.quantity, unitPrice: item.unitPrice, delegate: self)
return cell
}
}
当然,视图控制器将遵循该协议以接受对文本字段的更新并更新模型:
extension ViewController: ItemCellDelegate {
func cell(_ cell: ItemCell, didUpdateQuantity quantity: Decimal) {
guard let indexPath = tableView.indexPath(for: cell) else { return }
items[indexPath.row].quantity = quantity
updateTotal()
}
}
而且,正如您所看到的,如果可以,在更新模型之后,它也可以自动更新总数。
这里的关键是我们永远不要将单元格用作存放数据的地方。这些单元格仅用于(a)显示数据和(b)通知视图控制器是否需要了解任何更新。
我们努力明确区分职责,其中“视图”用于显示当前与屏幕上的控件并进行交互,而“模型”包含我们的所有数据。
答案 1 :(得分:0)
执行此操作的通常方法是拥有单元格的委托,并使ViewController成为该委托。每当单元格的值发生变化时,就将该值通过委托发送,以便视图控制器可以将所有这些值加起来。
那是快速的方法。
执行此操作的更好方法是为单元格提供一个数据源,以跟踪值。这样做会更好,因为随着单元格在屏幕上滚动和滚动,数据源可以跟踪值并在该索引路径再次可见时恢复它们。
由于数据源知道值是什么,所以对它们求和很简单。