在 Swift 中使用 UIStepper 更新 UITableViewCell 中的标签
Updating label in UITableViewCell with UIStepper in Swift
我是 Swift 初学者,我正在尝试制作一个简单的订餐应用程序。用户可以通过设置食物 name
、price
和 serving
来添加新订单。添加订单后,该订单将在 tableView 上显示为 FoodTableViewCell
,用户可以在每个单元格中使用名为 stepper
的 UIStepper 更改服务。每个订单都是一个 FoodItem
存储在一个名为 foodList
的数组中,您可以在 ShoppingListVC
.
中的 tableView 中看到列出的所有订单
我的问题是:当我按下 stepper
上的“+”或“-”按钮时,我的 servingLabel
没有更改为相应的值。 我尝试使用 NotificationCenter
将服务值传递给 stepper
,并在 stepperValueChanged
之后使用委托模式将新值存储回 food.serving
。但是,似乎仍然存在一些错误。在网上浏览了很多解决方案后,我有点困惑。感谢任何帮助。
更新
我按照@Tarun Tyagi 的建议删除了NotificationCenter
和addTarget
相关方法。现在我的 UIStepper 值变回 1,而 servingLabels 显示不同的服务数量。由于 NotificationCenter 没有帮助,我如何将标签和步进器值连接在一起?是否建议实施另一个委托?
这是我的代码(7 月 8 日更新):
FoodItem
class FoodItem: Equatable {
static func == (lhs: FoodItem, rhs: FoodItem) -> Bool {
return lhs === rhs
}
var name: String
var price: Int
var serving: Int
var foodID: String
init(name: String, price: Int, serving: Int) {
self.name = name
self.price = price
self.serving = serving
self.foodID = UUID().uuidString
}
}
ViewController
import UIKit
class ShoppingListVC: UIViewController, UITableViewDataSource, UITableViewDelegate {
var foodList = [FoodItem]()
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
...
for i in 1...5 {
let testItem = FoodItem(name: "Food\(i)", price: Int.random(in: 60...100), serving: Int.random(in: 1...10))
self.foodList.append(testItem)
}
}
// MARK: - Table view data source
...
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "foodCell", for: indexPath) as! FoodTableViewCell
let food = foodList[indexPath.row]
cell.nameLabel.text = food.name
cell.priceLabel.text = "$\(String(food.price)) / serving"
cell.servingLabel.text = "\(String(food.serving)) serving"
cell.stepper.tag = indexPath.row
cell.delegate = self
return cell
}
}
// MARK: - FoodTableViewCellDelegate Method.
extension ShoppingListVC: FoodTableViewCellDelegate {
func stepper(_ stepper: UIStepper, at index: Int, didChangeValueTo newValue: Double) {
let indexPath = IndexPath(item: index, section: 0)
guard let cell = tableView.cellForRow(at: indexPath) as? FoodTableViewCell else { return }
let foodToBeUpdated = foodList[indexPath.row]
print("foodToBeUpdated.serving: \(foodToBeUpdated.serving)")
foodToBeUpdated.serving = Int(newValue)
print("Value changed in VC: \(newValue)")
cell.servingLabel.text = "\(String(format: "%.0f", newValue)) serving"
}
}
TableViewCell
import UIKit
protocol FoodTableViewCellDelegate: AnyObject {
func stepper(_ stepper: UIStepper, at index: Int, didChangeValueTo newValue: Double)
}
class FoodTableViewCell: UITableViewCell {
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var priceLabel: UILabel!
@IBOutlet weak var servingLabel: UILabel!
@IBOutlet weak var stepper: UIStepper!
weak var delegate: FoodTableViewCellDelegate?
@IBAction func stepperValueChanged(_ sender: UIStepper) {
sender.minimumValue = 1
servingLabel.text = "\(String(format: "%.0f", sender.value)) serving"
// Pass the new value to ShoppingListVC and notify which cell to update using tag.
print("sender.value: \(sender.value)")
delegate?.stepper(stepper, at: stepper.tag, didChangeValueTo: sender.value)
}
override func awakeFromNib() {
super.awakeFromNib()
print(stepper.value)
}
}
小区配置:
protocol FoodTableViewCellDelegate: AnyObject {
func stepper(sender: FoodTableViewCell)
}
@IBAction func stepperButtonTapped(sender: UIStepper) {
delegate?.stepperButton(sender: self)
stepperLabel.text = "\(Int(countStepper.value))"
}
控制器配置:
cellForRow:
cell.countStepper.value = Double(foodList[indexPath.row].serving);
cell.stepperLabel.text = "\(Int(cell.countStepper.value))"
委托方法:
func stepperButton(sender: FoodTableViewCell) {
if let indexPath = tableView.indexPath(for: sender){
print(indexPath)
foodList[sender.tag].serving = Int(sender.countStepper.value)
}
}
最初 FoodTableViewCell
是 UIStepper
值更改的唯一目标(查看 FoodTableViewCell
中的 @IBAction
)。
当您使一个单元格出队显示在屏幕上时,您调用 -
cell.stepper.addTarget(self, action: #selector(stepperValueChanged(_:)), for: .valueChanged)
这会导致您的 ShoppingListVC
实例被添加为附加目标 每次 执行 cellForRow
调用。
需要解决的问题:
- 从 类.
中删除所有 NotificationCenter
相关代码
- 也删除
cell.stepper.addTarget()
行。
这会让您更好地了解为什么会这样。用这些更改更新你的问题,以防你仍然没有你想要的东西。
更新
// Inside cellForRow
cell.stepper.value = food.serving
请检查 value stepper pod 它将帮助您:Value stepper
集成 value stepper pod 并使用以下代码进行基本实现。
import ValueStepper
let valueStepper: ValueStepper = {
let stepper = ValueStepper()
stepper.tintColor = .whiteColor()
stepper.minimumValue = 0
stepper.maximumValue = 1000
stepper.stepValue = 100
return stepper
}()
override func viewDidLoad() {
super.viewDidLoad()
valueStepper.addTarget(self, action: "valueChanged:", forControlEvents: .ValueChanged)
}
@IBAction func valueChanged1(sender: ValueStepper) {
// Use sender.value to do whatever you want
}
它简化了自定义步进器 implantation.Take 价值步进器视图的出口 table table查看并使用它。
我是 Swift 初学者,我正在尝试制作一个简单的订餐应用程序。用户可以通过设置食物 name
、price
和 serving
来添加新订单。添加订单后,该订单将在 tableView 上显示为 FoodTableViewCell
,用户可以在每个单元格中使用名为 stepper
的 UIStepper 更改服务。每个订单都是一个 FoodItem
存储在一个名为 foodList
的数组中,您可以在 ShoppingListVC
.
我的问题是:当我按下 stepper
上的“+”或“-”按钮时,我的 servingLabel
没有更改为相应的值。 我尝试使用 NotificationCenter
将服务值传递给 stepper
,并在 stepperValueChanged
之后使用委托模式将新值存储回 food.serving
。但是,似乎仍然存在一些错误。在网上浏览了很多解决方案后,我有点困惑。感谢任何帮助。
更新
我按照@Tarun Tyagi 的建议删除了NotificationCenter
和addTarget
相关方法。现在我的 UIStepper 值变回 1,而 servingLabels 显示不同的服务数量。由于 NotificationCenter 没有帮助,我如何将标签和步进器值连接在一起?是否建议实施另一个委托?
这是我的代码(7 月 8 日更新):
FoodItem
class FoodItem: Equatable {
static func == (lhs: FoodItem, rhs: FoodItem) -> Bool {
return lhs === rhs
}
var name: String
var price: Int
var serving: Int
var foodID: String
init(name: String, price: Int, serving: Int) {
self.name = name
self.price = price
self.serving = serving
self.foodID = UUID().uuidString
}
}
ViewController
import UIKit
class ShoppingListVC: UIViewController, UITableViewDataSource, UITableViewDelegate {
var foodList = [FoodItem]()
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
...
for i in 1...5 {
let testItem = FoodItem(name: "Food\(i)", price: Int.random(in: 60...100), serving: Int.random(in: 1...10))
self.foodList.append(testItem)
}
}
// MARK: - Table view data source
...
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "foodCell", for: indexPath) as! FoodTableViewCell
let food = foodList[indexPath.row]
cell.nameLabel.text = food.name
cell.priceLabel.text = "$\(String(food.price)) / serving"
cell.servingLabel.text = "\(String(food.serving)) serving"
cell.stepper.tag = indexPath.row
cell.delegate = self
return cell
}
}
// MARK: - FoodTableViewCellDelegate Method.
extension ShoppingListVC: FoodTableViewCellDelegate {
func stepper(_ stepper: UIStepper, at index: Int, didChangeValueTo newValue: Double) {
let indexPath = IndexPath(item: index, section: 0)
guard let cell = tableView.cellForRow(at: indexPath) as? FoodTableViewCell else { return }
let foodToBeUpdated = foodList[indexPath.row]
print("foodToBeUpdated.serving: \(foodToBeUpdated.serving)")
foodToBeUpdated.serving = Int(newValue)
print("Value changed in VC: \(newValue)")
cell.servingLabel.text = "\(String(format: "%.0f", newValue)) serving"
}
}
TableViewCell
import UIKit
protocol FoodTableViewCellDelegate: AnyObject {
func stepper(_ stepper: UIStepper, at index: Int, didChangeValueTo newValue: Double)
}
class FoodTableViewCell: UITableViewCell {
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var priceLabel: UILabel!
@IBOutlet weak var servingLabel: UILabel!
@IBOutlet weak var stepper: UIStepper!
weak var delegate: FoodTableViewCellDelegate?
@IBAction func stepperValueChanged(_ sender: UIStepper) {
sender.minimumValue = 1
servingLabel.text = "\(String(format: "%.0f", sender.value)) serving"
// Pass the new value to ShoppingListVC and notify which cell to update using tag.
print("sender.value: \(sender.value)")
delegate?.stepper(stepper, at: stepper.tag, didChangeValueTo: sender.value)
}
override func awakeFromNib() {
super.awakeFromNib()
print(stepper.value)
}
}
小区配置:
protocol FoodTableViewCellDelegate: AnyObject {
func stepper(sender: FoodTableViewCell)
}
@IBAction func stepperButtonTapped(sender: UIStepper) {
delegate?.stepperButton(sender: self)
stepperLabel.text = "\(Int(countStepper.value))"
}
控制器配置:
cellForRow:
cell.countStepper.value = Double(foodList[indexPath.row].serving);
cell.stepperLabel.text = "\(Int(cell.countStepper.value))"
委托方法:
func stepperButton(sender: FoodTableViewCell) {
if let indexPath = tableView.indexPath(for: sender){
print(indexPath)
foodList[sender.tag].serving = Int(sender.countStepper.value)
}
}
最初 FoodTableViewCell
是 UIStepper
值更改的唯一目标(查看 FoodTableViewCell
中的 @IBAction
)。
当您使一个单元格出队显示在屏幕上时,您调用 -
cell.stepper.addTarget(self, action: #selector(stepperValueChanged(_:)), for: .valueChanged)
这会导致您的 ShoppingListVC
实例被添加为附加目标 每次 执行 cellForRow
调用。
需要解决的问题:
- 从 类. 中删除所有
- 也删除
cell.stepper.addTarget()
行。
NotificationCenter
相关代码
这会让您更好地了解为什么会这样。用这些更改更新你的问题,以防你仍然没有你想要的东西。
更新
// Inside cellForRow
cell.stepper.value = food.serving
请检查 value stepper pod 它将帮助您:Value stepper
集成 value stepper pod 并使用以下代码进行基本实现。
import ValueStepper
let valueStepper: ValueStepper = {
let stepper = ValueStepper()
stepper.tintColor = .whiteColor()
stepper.minimumValue = 0
stepper.maximumValue = 1000
stepper.stepValue = 100
return stepper
}()
override func viewDidLoad() {
super.viewDidLoad()
valueStepper.addTarget(self, action: "valueChanged:", forControlEvents: .ValueChanged)
}
@IBAction func valueChanged1(sender: ValueStepper) {
// Use sender.value to do whatever you want
}
它简化了自定义步进器 implantation.Take 价值步进器视图的出口 table table查看并使用它。