簡體   English   中英

如何使用UITableViewCell中的委托方法設置UISlider

[英]How to set a UISlider using a delegate method from UITableViewCell

我正在設置MainViewControllerPopUpViewController

MainVC我有一個滑塊,它代表從0到800厘米的高度。 同樣在這里,我有2個標簽,分別表示以公尺+英寸米+厘米為單位的厘米的轉換。

HeightTableViewCell ,我具有所有的插座和滑塊,並且那里有一個與MainVC通信的MainVC

PopUpViewController ,我有一個保存按鈕和3個UITextFields (厘米,英尺和英寸)。 當我按下保存按鈕時,我想在MainVC中將滑塊設置為正確的值,並在標簽中顯示轉換。

我需要使用該委托方法設置UISlider ,因為我無法訪問TableViewCellUISlider嗎?

我已經嘗試過將數據傳遞給代表。 還有其他更好的方法嗎?

這是我的MainVC:

class MainViewController: UIViewController {

    var sliderValue: Float = 0.0    

    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

extension MainViewController: UITableViewDelegate, UITableViewDataSource {

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "heightCell", for: indexPath) as! HeightTableViewCell
        cell.configVehicleHeightCell(sliderValue)
        cell.delegate = self

        return cell
    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        switch indexPath.row {
        case 0: return 150
        default:
            return 150
        }
    }
}

// Receive data from the Cell to MainVC
extension MainViewController: HeightCellDelegate {

    func heightSliderValueChanged(_ slider: UISlider, _ feetsLabel: UILabel, _ metersLabel: UILabel) {

        let currentValue = Int(slider.value)
        let meters = currentValue / 100
        let centimeters = currentValue % 100
        let inches = currentValue < 3 ? 0 : round(Double(currentValue) / 2.54)
        let feet = round(inches / 12)
        let inch = round(inches.truncatingRemainder(dividingBy: 12))

        feetsLabel.text = "\(feet) ft" + " \(inch)\""
        metersLabel.text = "\(meters) m" + " \(centimeters) cm"
    }
}

// Receive data (centimeters) from the PopUp to MainVC
extension MainViewController: HeightPopUpDelegate {

    func receiveHeightMetric(centimeters: Float?) {
        print("\n\nMetric Data received")
        print("Centimeters: \(centimeters ?? 0)")

        sliderValue = Float(centimeters ?? 0)
        tableView.reloadData()
    }

    func receiveHeightImperial(feet: Int?, inches: Int?) {

        print("\n\nImperial Data received")
        print("Feet: \(feet ?? 0)")
        print("Inches: \(inches ?? 0)")
    }

    // Receive the data from PopUpViewController
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        if segue.identifier == "goToHeight" {
            let vc: PopUpViewController = segue.destination as! PopUpViewController
            vc.delegate = self
        }
    }
}

這是我的MainVC單元:

protocol HeightCellDelegate {
    func heightSliderValueChanged(_ slider: UISlider, _ feetsLabel: UILabel, _ metersLabel: UILabel)
}

class HeightTableViewCell: UITableViewCell {

    // Interface Links
    @IBOutlet weak var heightLabelTitle: UILabel!
    @IBOutlet weak var heightSlider: UISlider!
    @IBOutlet weak var heightFeetsLabel: UILabel!
    @IBOutlet weak var heightMetersLabel: UILabel!

    // Properties
    var delegate: HeightCellDelegate?

    override func awakeFromNib() {
        super.awakeFromNib()
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    }

   func configVehicleHeightCell(_ value : Float){

    heightSlider.value = value
    heightLabelTitle.text = "Height"


    let meters  = Int((value) / 100)
    let centimeters  = Int(value.truncatingRemainder(dividingBy: 100))
    let inches = Int(value) < 3 ? 0 : round((value) / 2.54)
    let feet = Int(round(inches / 12))
    let inch = Int(round(inches.truncatingRemainder(dividingBy: 12)))

    heightFeetsLabel.text = "\(feet) ft" + " \(inch)\""
    heightMetersLabel.text = "\((meters)) m" + " \((centimeters)) cm"
}

    @IBAction func heightValueChanged(_ sender: UISlider) {

        configVehicleHeightCell(sender.value)
    }
}

這是我的PopUpVC代碼:

protocol HeightPopUpDelegate {
    func receiveHeightMetric(centimeters: Int?)
    func receiveHeightImperial(feet: Int?, inches: Int?)
}

class PopUpViewController: UIViewController {

    // Interface Links
    @IBOutlet weak var centimetersTextField: UITextField!
    @IBOutlet weak var feetTextField: UITextField!
    @IBOutlet weak var inchesTextField: UITextField!
    @IBOutlet weak var labelForOr: UILabel!
    @IBOutlet weak var popUpView: UIView!
    @IBOutlet weak var cancelBtnOutlet: UIButton!
    @IBOutlet weak var saveBtnOutlet: UIButton!

    // Properties
    var delegate: HeightPopUpDelegate?

    override func viewDidLoad() {
        super.viewDidLoad()
        setupViews()
    }

    // Dismiss the popup when user press the Cancel btn
    @IBAction func cancelBtnTapped(_ sender: UIButton) {

        dismiss(animated: true, completion: nil)
    }

    // Save the data and send it back when user press the Save btn
    @IBAction func saveBtnTapped(_ sender: UIButton) {

        checkImperialOrMetricTextfields()
        dismiss(animated: true, completion: nil)
    }

    // Check if the textfields contains Metric or Imperial height. If everything is OK then send the data back.
    func checkImperialOrMetricTextfields(){

        if ((!(centimetersTextField.text?.isEmpty)!) && (!(feetTextField.text?.isEmpty)! || !(inchesTextField.text?.isEmpty)!)) {

            showAlertWithTitle(title: "Error", message: "Enter either metric OR imperial height.")
            clearTextFields()
        }
        if ((centimetersTextField.text?.isEmpty)! && (feetTextField.text?.isEmpty)! && (inchesTextField.text?.isEmpty)!) {

            showAlertWithTitle(title: "Error", message: "Enter either metric OR imperial height.")
            clearTextFields()
        }
        else{
            sendDataBack()
        }
    }

    // Clear textfields
    func clearTextFields(){

        centimetersTextField.text = ""
        feetTextField.text = ""
        inchesTextField.text = ""
    }

    // Function used to send data back from the PopUp to MainVC
    func sendDataBack(){

        if delegate != nil{
            delegate?.receiveHeightMetric(centimeters: Int(centimetersTextField?.text ?? "0"))
            delegate?.receiveHeightImperial(feet: Int(feetTextField?.text ?? "0"), inches: Int(inchesTextField?.text ?? "0"))
        }
    }

    // Setup the design for outlets
    func setupViews(){

        popUpView.layer.cornerRadius = 20
        popUpView.layer.masksToBounds = true

        cancelBtnOutlet.layer.cornerRadius = 5
        cancelBtnOutlet.layer.borderWidth = 0.5
        cancelBtnOutlet.layer.borderColor = UIColor.black.cgColor

        saveBtnOutlet.layer.cornerRadius = 5
        saveBtnOutlet.layer.borderWidth = 0.5
        saveBtnOutlet.layer.borderColor = UIColor.black.cgColor
    }

    // Function to hide the Popup when the user click anywhere on the screen
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touch = touches.first
        if touch?.view == self.view {
            dismiss(animated: true, completion: nil)
        }
    }

    // Show an alert view with Title
    func showAlertWithTitle(title: String = "", message: String) {
        let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
        let OKAction = UIAlertAction(title: "OK", style: .default, handler: nil)
        alertController.addAction(OKAction)
        self.present(alertController, animated: true, completion: nil)
    }
}

當我在PopUp中設置某些內容並單擊“保存”時,我會在控制台中從該文本字段中獲取值:

Metric Data received
Centimeters: 0

Imperial Data received
Feet: 23
Inches: 45

如果正在幫助任何人,這是這個小例子的鏈接: https : //github.com/tygruletz/ImperialAndMetricMeasurement

非常感謝您閱讀本文,希望我提供正確的信息。

我進行了一些更改,以下是cm/m的工作示例,

  1. HeightTableViewCell ,在HeightTableViewCell設置標簽和滑塊。 我將Int設置為Float的地方很少。

     func configVehicleHeightCell(_ value : Float){ heightSlider.value = value heightLabelTitle.text = "Height" let meters = Int((value) / 100) let centimeters = Int(value.truncatingRemainder(dividingBy: 100)) let inches = Int(value) < 3 ? 0 : round((value) / 2.54) let feet = Int(round(inches / 12)) let inch = Int(round(inches.truncatingRemainder(dividingBy: 12))) heightFeetsLabel.text = "\\(feet) ft" + " \\(inch)\\"" heightMetersLabel.text = "\\((meters)) m" + " \\((centimeters)) cm" } 
  2. heightValueChanged ,您不再需要委托

     @IBAction func heightValueChanged(_ sender: UISlider) { configVehicleHeightCell((sender.value)) } 
  3. MainVC ,創建var sliderValue : Float = 0.0

  4. 在cellForRow中, cell.configVehicleHeightCell(sliderValue)

  5. 最后,當用戶在警報中輸入數據時(在cm文本字段中有效)

     func receiveHeightMetric(centimeters: Float?) { print("\\n\\nMetric Data received") print("Centimeters: \\(centimeters ?? 0)") sliderValue = centimeters ?? 0 mtTableView.reloadData() } 

輸出:

在此處輸入圖片說明

編輯

對於feet/inch ,僅在下面做

func receiveHeightImperial(feet: Int?, inches: Int?){
   // 1. convert feet, inch into centimeter.    
   // 2. If either of feet/inch is nil then consider it as zero, for safety
   // 3. Now, sliderValue = new_cm_value (value that you calculated from feet/inch)
   // 4. Now reloadData().
}

您只有一個單元格,因此您可以:

MainVC

@IBOutlet weak var tableView: UITableView!

    func receiveHeightMetric(centimeters: Int?) {
        print("\n\nMetric Data received")
        print("Centimeters: \(centimeters ?? 0)")

        let cell = self.tableView.cellForRow(at: IndexPath(row: 0, section: 0)) as! HeightTableViewCell
        cell.refresh(centimeters: centimeters)
    }

    func receiveHeightImperial(feet: Int?, inches: Int?) {

        print("\n\nImperial Data received")
        print("Feet: \(feet ?? 0)")
        print("Inches: \(inches ?? 0)")


        let cell = self.tableView.cellForRow(at: IndexPath(row: 0, section: 0)) as! HeightTableViewCell
        cell.refresh(feet: feet, inches: inches)
    }

HeightTableViewCell

    func refresh(centimeters: Int?) {
        print("\n\nMetric Data received in cell")
        print("Centimeters: \(centimeters ?? 0)")
    }
    func refresh(feet: Int?, inches: Int?) {

        print("\n\nImperial Data received in cell")
        print("Feet: \(feet ?? 0)")
        print("Inches: \(inches ?? 0)")
    }

您可以為UIViewController創建一個協議,該協議將由UITableViewCell遵循。

說-

protocol UpdateSlider : class {

    func updateSlider(with value : CGFloat)

}

現在您的MainViewController將具有該協議的變量,並且您將通過單元格的引用在cellForRowAt方法中為該變量分配一個值。

class MainViewController : UIViewController {

    weak var delegate : UpdateSlider?
}


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "heightCell", for: indexPath) as! HeightTableViewCell
    cell.configVehicleHeightCell()
    cell.delegate = self
    self.delegate = cell
    return cell
}

每當您想更新滑塊的值時,只需調用MainViewController的委托方法即可。

self.delegate?.updateSlider(with value : <#CustomValue#>)

PS-您隨時可以在cellForRowAt設置當前值,並在需要時重新加載單元格。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM