Use Inputs from user as Min & Max values for UISlider

73 Views Asked by At

I have 2 x UITextFields for the user to put values in. I want to use those values as the min & max values for the UISlider. I have been struggling with this for 2 days already.

This is my current code:

import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var sensorMinText: UITextField!
    @IBOutlet weak var sensorMaxText: UITextField!
    @IBOutlet weak var sliderLabel: UILabel!
    
    var sensorMin: String?
    var sensorMax: String?
    
    override func viewDidLoad() {
        super.viewDidLoad()
              
        let tap = UITapGestureRecognizer(target: self, action:       #selector(UIInputViewController.dismissKeyboard))

        view.addGestureRecognizer(tap)
        
        Slider.value = 0
        Slider.minimumValue = 
        Slider.maximumValue = 
        sliderLabel.text = String(Int(Slider.value))
    }

    @objc func dismissKeyboard() {
        view.endEditing(true)
    }

    @IBAction func sMinInput(_ sender: Any) {
        sensorMin = sensorMinText.text
    }
    
    @IBAction func sMaxInput(_ sender: Any) {
        sensorMax = sensorMaxText.text
    }
    
    @IBOutlet weak var Slider: UISlider!
    
    @IBAction func sliderChanged(_ sender: UISlider) {
        sliderLabel.text = String(Int(sender.value))
    } 
}
3

There are 3 best solutions below

0
Neph On BEST ANSWER

I managed to get the App working as intended. Create a func above viewDidLoad that changes the Slider's minimumValue and maximumValue properties to the user's inputs i from minTextField and maxTextField. Call the func in the minimum (sMinInput) and maximum (sMaxInput) input senders respectively.

import UIKit

class ViewController: UIViewController {
    
    @IBOutlet weak var sensorMinText: UITextField!
    @IBOutlet weak var sensorMaxText: UITextField!
    @IBOutlet weak var sliderLabel: UILabel!

    //Below create func to set Slider's values to user's inputs.
    func changeSlider() {
        Slider.minimumValue = Float(sensorMinText.text!) ?? 0.0
        Slider.maximumValue = Float(sensorMaxText.text!) ?? 0.0
    }    
    
    override func viewDidLoad() {
        super.viewDidLoad()
              
        let tap = UITapGestureRecognizer(target: self, action: 
        #selector(UIInputViewController.dismissKeyboard))

        view.addGestureRecognizer(tap)
        
        sliderLabel.text = String(Int(Slider.value))
    }

    @objc func dismissKeyboard() {
        view.endEditing(true)
    }

    //Call func to update Slider values when user inputs min value
    @IBAction func sMinInput(_ sender: Any) {
        changeSlider()
    }

    //Call func to update Slider values when user inputs max value
    @IBAction func sMaxInput(_ sender: Any) {
        changeSlider()
    }
    
    @IBOutlet weak var Slider: UISlider!
    
    @IBAction func sliderChanged(_ sender: UISlider) {
        sliderLabel.text = String(Int(sender.value))
    }   
}
2
Duncan C On

You don't say what platform you are working on, although your code references UIKit, so I am assuming this is for iOS. You should add an iOS tag to your question.

You don't have any code that attempts to set the max and min of your slider.

Have you tried to tackle that part yet?

You need to have numeric properties (not strings) for your slider max and slider min values. When the user enters a new min or max value, you need to validate the input, and then update the numeric max/min value.

You could add a didSet on your max and min inputs that would apply the new limit to your UISlider.

If you look in the docs for UISlider it says:


Accessing the slider’s value limits

var minimumValue: Float

The minimum value of the slider.

var maximumValue: Float

The maximum value of the slider.


Those are the slider properties you would need to modify.

0
vadian On

That's a good application possibility for the Combine framework.

First things first

import Combine

Then add an extension of UITextField to get notified on textDidChange

extension UITextField {
   func textDidChangePublisher() -> AnyPublisher<String, Never> {
       NotificationCenter.default
           .publisher(for: UITextField.textDidChangeNotification, object: self)
           .map { ($0.object as? UITextField)?.text  ?? "" }
           .eraseToAnyPublisher()
   }
 }

In the view controller on the top level create a property to hold the subscriptions

var subscriptions = Set<AnyCancellable>()

and in viewDidLoad implement the subscriptions which update the min and max properties of the slider when the text changes respectively.

sensorMinText.textDidChangePublisher()
    .compactMap(Float.init)
    .sink { [unowned self] value in
        // check if the minimum value is equal or less than the maximum value
        if value <= self.slider.maximumValue {
            self.slider.minimumValue = value
        }
    }
    .store(in: &subscriptions)

sensorMaxText.textDidChangePublisher()
    .compactMap(Float.init)
    .sink { [unowned self] value in
        // check if the maximum value is equal or greater than the minimum value
        if value >= self.slider.minimumValue {
            self.slider.maximumValue = value
        }
    }
    .store(in: &subscriptions)

Important: The keyboard type of both text fields must be Decimal Pad and assign default min and max values to both the text fields and the slider (by the way name the slider IBOutlet lowercase)