доступ к сохраненным значениям из tableViewCell и сохранение их в FirebaseDatabase

#ios #swift #uitableview #slider

#iOS #swift #uitableview #ползунок

Вопрос:

У меня есть tableViewCell, внутри которого есть ползунок диапазона. Я бы хотел, чтобы значения из ползунка диапазона сохранялись в firebase, когда пользователь нажимает handleSave() . Я могу распечатать значения, когда пользователь перемещает ползунок диапазона внутри 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, я могу успешно распечатать значения ползунка диапазона. Но когда я пытаюсь напечатать значение rangeSliders внутри tableViewVC, оно не работает. Единственный способ сохранить эту информацию в firebase — это иметь доступ к ее значению. Чего мне не хватает? Если я могу распечатать инструкции внутри tableViewVC, я могу затем сохранить их в базе данных.

Комментарии:

1. Как всегда, ячейка — это объект для отображения данных, и ничего больше. это не место для хранения чего-либо. Если ячейка содержит элементы пользовательского интерфейса, которые изменяют источник данных, вы несете ответственность за обновление модели. Затем получите данные из модели , а не из представления . И вам настоятельно не рекомендуется создавать ячейки с указанным инициализатором в табличном представлении. Используйте их повторно.

Ответ №1:

Проблемы с вашим кодом

  1. В методе handelSave при попытке получить значение из ячейки вы ожидаете получить значения ползунка, сделанные пользователем, но на самом деле вы создаете новый экземпляр AgeRangeCell со значениями по умолчанию. Чтобы решить эту проблему, вам нужно использовать шаблон делегирования, как я его опубликовал.

    Удалите эту строку в методе handleSave: пусть costRangeCell = AgeRangeCell(стиль: .default, повторный идентификатор: nil)

    Для значений minSeekingCost и maxSeekingCost в классе необходимо создать дополнительный параметр для хранения этих значений.

  2. При создании AgeRangeCell вы не передаете идентификатор повторного использования, и это может привести к снижению производительности прокрутки таблицы.

Возможные решения

  1. Используйте MVC и скороговорку делегирования. У вас должен быть держатель значения для вашего возраста. Ниже приведен пример того, как это может быть достигнуто.
  2. Создайте пользовательский интерфейс с помощью SwiftUI. Вместе с 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)
    }
}
  

ViewController

 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
    }
}
  

Комментарии:

1. Спасибо вам за это, я пытаюсь понять процесс и применить его к своему приложению. но у меня все еще возникают проблемы. Например, я использую RangeSlider с двумя дескрипторами, и как мне получить значения из обоих? Я просто не понимаю, почему я могу печатать значения внутри раздела indexPath, но я не могу получить те же значения для сохранения

2. Есть ли более простой способ сохранить это значение?

3. Я все еще сталкиваюсь с той же проблемой. Я думаю, что отключение может быть связано с тем, что я пытаюсь реализовать ваш ответ с помощью кода

4. Я не понимаю, как я могу печатать низкие и высокие значения внутри indexPath в консоль, но не сохранять значение при его сохранении.

5. Вы можете поделиться где-нибудь кодом. Я посмотрю.