【问题标题】:access stored values from a tableViewCell and save them to firebaseDatabase从 tableViewCell 访问存储的值并将它们保存到 firebaseDatabase
【发布时间】:2020-11-17 05:18:53
【问题描述】:

我有一个 tableViewCell,里面有一个范围滑块。当用户点击handleSave()时,我希望将范围滑块中的值保存到firebase。当用户在 tableViewCell 内滑动范围滑块时,我可以打印出这些值,但我不能从 tableViewCell 本身保存这个值,也不能从 tableViewVC 打印值。当我尝试从 tableViewVC 打印值时,我在控制台中看不到任何内容。但如果我要从我的 tableViewCell 本身打印它们,那么它工作得很好。

我用来尝试从 tableViewVC 打印值的代码是,

   if indexPath.section == 2 {
        
        let costRangeCell = AgeRangeCell(style: .default, reuseIdentifier: nil)
        costRangeCell.rangeSlider.minimumValue = 5
        costRangeCell.rangeSlider.maximumValue = 200
        costRangeCell.rangeSlider.lowValue = 5
        costRangeCell.rangeSlider.highValue = 200
        costRangeCell.rangeSlider.minimumDistance = 20
        costRangeCell.delegate = self
        
        return costRangeCell
    }


var lowCost: Double = 0.0
var highCost: Double = 0.0

func didChange(lowVal: Double, highVal: Double, forCell cell: AgeRangeCell) {
    self.lowCost = lowVal
    self.highCost = highVal
}

在上面的打印语句中,我可以看到用户选择的范围滑块的值。

我打算如何保存数据也在 tableViewVc 中。

    @objc fileprivate func handleSave() {
       guard let uid = Auth.auth().currentUser?.uid else { return }
    let docData: [String: Any] = [
        "minSeekingCost": lowCost,
        "maxSeekingCost": highCost
        
    ]
    
    self.updateUserDataIntoDatabseWithUID(uid: uid, values: docData as [String : AnyObject])
    print("Finished saving user info")
    self.dismiss(animated: true, completion: {
        print("Dismissal complete")
        print(lowVal)
        print(highVal)
    })
}

当我尝试查看此处打印的值时,它只显示 0 和 1,而不是 rangeSlider 的实际数字

   protocol AgeRangeCellDelegate {
func didChange(lowVal: Double, highVal: Double, forCell cell: AgeRangeCell)
 }

 class AgeRangeCell: UITableViewCell {

let rangeSlider: AORangeSlider = {
    let slider = AORangeSlider()
    slider.stepValue = 5
    slider.trackColor = GREEN_Theme
    slider.addTarget(self, action: #selector(didChangeCost), for: .touchUpInside)
    return slider
}()

var delegate: AgeRangeCellDelegate?
var user: User?
let lowLabel = UILabel()
let highLabel = UILabel()

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    commonInit()
}

@objc func didChangeCost(_ sender: AORangeSlider) {
    delegate?.didChange(lowVal: sender.lowValue, highVal: sender.highValue, forCell: self)
        }

required init?(coder: NSCoder) {
    super.init(coder: coder)

   }

 }

当打印语句在ageRangeCell 内时,我可以成功打印范围滑块的值。但是当我尝试在 tableViewVC 内打印 rangeSliders 值时,它不起作用。我将这些信息保存到 firebase 的唯一方法是如果我可以访问它的值。我错过了什么?如果我可以在 tableViewVC 中打印语句,我就可以将它们保存到数据库中。

【问题讨论】:

  • 与往常一样,单元格是显示数据的对象,仅此而已。它不是存放东西的地方。如果单元格包含修改数据源的 UI 元素,则您负责更新模型。然后从 model 中获取数据,而不是从 view 中获取数据。并且强烈建议您不要在表格视图中使用指定的初始化程序创建单元格。重复使用它们。

标签: ios swift uitableview slider


【解决方案1】:

您的代码存在问题

  1. handelSave 方法中,当您尝试从单元格中获取值时,您希望获得用户制作的滑块值,但实际上您正在创建 AgeRangeCell 的新实例使用默认值。要解决这个问题,您需要像我发布的那样使用 delegation 模式。

    在handleSave方法中删除这一行: 让 costRangeCell = AgeRangeCell(style: .default, reuseIdentifier: nil)

    对于类中的 minSeekingCost 和 maxSeekingCost 值,必须创建附加参数来保存这些值。

  2. 在创建 AgeRangeCell 时,您没有传递重用标识符,它会导致表格视图滚动性能变慢。

可能的解决方案

  1. 使用 MVC 和委托模式。你需要有适合你年龄的价值持有者。下面是如何实现它的示例。
  2. 使用 SwiftUI 构建 UI。与 Combine 一起可以消除委托模式。

出于这个原因,我确实使用了故事板,因此需要的代码更少。

AgeRangeCell 和 AgeRangeCellDelegate

protocol AgeRangeCellDelegate {
    func didChange(age: Float, forCell cell: AgeRangeCell)
}

class AgeRangeCell: UITableViewCell {
    
    var delegate: AgeRangeCellDelegate?
    
    @IBOutlet weak var slider: UISlider!
    
    @IBAction func didChangeAge(_ sender: UISlider) {
        delegate?.didChange(age: sender.value, forCell: self)
    }
}

视图控制器

class ViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!
    
    var age: Float = 0
    
    @IBAction func didTapSave(_ sender: Any) {
        // TODO: Save age to Firestore
        
        guard let uid = Auth.auth().currentUser?.uid else { return }
        let docData: [String: Any] = [
            "age": age
        ]
        
        updateUserDataIntoDatabseWithUID(uid: uid, values: docData as [String : AnyObject])
    }
}

UITableViewDataSource

extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        1
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "AgeRangeCell") as! AgeRangeCell
        
        cell.delegate = self
        cell.slider.value = age
        
        return cell
    }
}

AgeRangeCellDelegate

extension ViewController: AgeRangeCellDelegate {
    func didChange(age: Float, forCell cell: AgeRangeCell) {
        self.age = age
    }
}

【讨论】:

  • 谢谢你,我正在努力了解这个过程并申请我的申请。但我仍然有问题。例如,我正在使用一个有两个句柄的 rangeSlider,我如何从这两个句柄中获取值?我只是不明白为什么我可以在 indexPath 部分中打印这些值,但我无法获得相同的值来存储
  • 有没有更简单的方法来存储这个值?
  • 我仍然面临同样的问题。我认为断开连接可能与我试图通过代码实现您的答案有关
  • 我不明白如何将 indexPath 中的低值和高值打印到控制台中,但在保存时不存储值。
  • 您可以在某处分享代码。我去看看。
猜你喜欢
  • 1970-01-01
  • 2021-10-27
  • 2023-03-12
  • 2015-11-16
  • 1970-01-01
  • 1970-01-01
  • 2016-03-31
  • 2015-06-27
  • 1970-01-01
相关资源
最近更新 更多