0

I'm trying to read ints from an UIPickerView, I've already done this but it's only a print on an UILabel. this time I need the data so I can put sounds for each number, so I can make a queue announcer (it's a 3-digit UIPickerView and starts from "001" to "999". see I don't know the code to give each component's selected number a sound. (I've already imported the sounds via AVFoundation but I won't paste it here in my code). And as I've mentioned in the comments, Converting isn't my problem. So this question is new. Here's what I have so far:

import UIKit
import AVFoundation

class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {
    //Picker View Settings
    @IBOutlet weak var label: UILabel!
    @IBOutlet weak var pickerView: UIPickerView!

    let numbers = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]

    func numberOfComponents(in pickerView: UIPickerView) -> Int {
       return 3
    }

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
       return numbers[row]
    }

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
       return numbers.count
    }

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        let val1 = numbers[pickerView.selectedRow(inComponent: 0)]
        let val2 = numbers[pickerView.selectedRow(inComponent: 1)]
        let val3 = numbers[pickerView.selectedRow(inComponent: 2)]

        label.text = "\(val1) \(val2) \(val3)"
    }

    //"Next" Button Setting 
    fileprivate func num(_ i: Int) -> Int {
        return pickerView.selectedRow(inComponent: i)
    }

    @IBAction func buttonPressed() {
        let currentNum = num(0) * 100 + num(1) * 10 + num(2)
        let nextNum = currentNum + 1

        pickerView.selectRow(nextNum % 1000 / 100, inComponent: 0, animated: true)
        pickerView.selectRow(nextNum % 100 / 10, inComponent: 1, animated: true)
        pickerView.selectRow(nextNum % 10, inComponent: 2, animated: true)

        changeLabelText()
    }

    fileprivate func changeLabelText() {
        label.text = "\(num(0)) \(num(1)) \(num(2))"
    }

    //Announcer Button
    @IBAction func soundPlayed(_ sender: Any) {
        //Don't have any function yet, because of my question.
    }
rmaddy
  • 314,917
  • 42
  • 532
  • 579
Shahin
  • 71
  • 2
  • 11
  • Possible duplicate of [Swift - Converting String to Int](https://stackoverflow.com/questions/24115141/swift-converting-string-to-int) – Losiowaty Sep 18 '17 at 23:41
  • Pal I don't want to convert anything to anything. I'm looking for a way to "read" ints from the pickerview as in a way to run functions on them like playing sounds. ever heard announcers saying: Number 34 to Console #2? that's what I'm trying to do. @Losiowaty – Shahin Sep 18 '17 at 23:45

1 Answers1

2

There is a much better way to do what you are trying to do with this code. Don't work with strings. Work with numbers.

The following code keeps track of the current value as an Int. It's updated as the picker values change. Make use of currentValue in any method that needs to know the current value of the pickers.

The idea is that you do not use views to keep data. Views only show data. Keep the data stored separately.

class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {
    @IBOutlet weak var label: UILabel!
    @IBOutlet weak var pickerView: UIPickerView!

    var currentValue = 0

    func updateCurrentValue() {
        // Use max(0, xxx) since `selectedRow` can return -1 if the component has no selection
        let hundreds = max(0, pickerView.selectedRow(inComponent: 0))
        let tens = max(0, pickerView.selectedRow(inComponent: 1))
        let ones = max(0, pickerView.selectedRow(inComponent: 2))

        currentValue = hundreds * 100 + tens * 10 + ones
    }

    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 3
    }

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        return String(row)
    }

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return 10 // digits 0 - 9
    }

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        updateCurrentValue()

        changeLabelText()
    }

    @IBAction func buttonPressed() {
        currentValue = (currentValue + 1) % 1000

        pickerView.selectRow(currentValue / 100, inComponent: 0, animated: true)
        pickerView.selectRow(currentValue / 10 % 10, inComponent: 1, animated: true)
        pickerView.selectRow(currentValue % 10, inComponent: 2, animated: true)

        changeLabelText()
    }

    fileprivate func changeLabelText() {
        label.text = String(currentValue)
    }

    @IBAction func soundPlayed(_ sender: Any) {
        // Do something with currentValue
    }
rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • Thanks, I'm getting somewhere with your code now. but I had this "NEXT" UIButton in my app that whenever it was pressed, the UIPickerView's Wheel moved one number ahead. now with your coding structure, it ain't working anymore, could you pass a code so I can rebuild that? @rmaddy – Shahin Sep 19 '17 at 00:05
  • The code for the "next" button is still there - `buttonPressed`. It should be working. What happens exactly when you tap the button? – rmaddy Sep 19 '17 at 00:12
  • it moves only one digit on the wheel and doesn't do more when you keep pressing, and the UILabel doesn't update (not only that one digit it moves). @rmaddy – Shahin Sep 19 '17 at 00:15
  • 1
    Oops - I see the problem. In my `buttonPressed` method you need to remove the `let` before `currentValue`. – rmaddy Sep 19 '17 at 00:17