swiftavfoundationuipickerviewavspeechsynthesizer

How to sort AVSpeechSynthesisVoice.speechVoices()


I'm a beginner, and I'm while working on this, I noticed that the picker view isn't sorted

enter image description here

Obviously Chinese does not come after Turkish, so how do I sort it up? I've been looking at my code for hours and can't seem to figure out how to get it sorted. Here's my complete code.

Thanks

import AVFoundation
import UIKit

class SettingsView: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
    @IBOutlet var pickerView: UIPickerView!

    var voicesArray: [String] = []
    let speechVoices = AVSpeechSynthesisVoice.speechVoices()

    override func viewDidLoad() {
        super.viewDidLoad()

        pickerView.delegate = self
        pickerView.dataSource = self
    }

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

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

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        let language = Locale.current.localizedString(forLanguageCode: speechVoices[row].language)!
        let languageCode = speechVoices[row].language

        var regionCode:String = ""
        for region in Locale.isoRegionCodes {
            // Test if provided region codes has voices or not
            if languageCode.contains(region) {
                regionCode = region
            }
        }

        let country = Locale.current.localizedString(forRegionCode: String(regionCode))

        return "\(language) (\(country ?? ""))"
    }

    @IBAction func done(_ sender: UIButton) {
        dismiss(animated: true, completion: nil)
    }
}


Solution

  • Chinese (zh) definitely comes after Turkey (tr), so these appear already sorted by region code. If you want to sort by something else (I assume their display name in the locale language), then you can sort them when you set up your list of elements for the picker. For example:

    let speechVoices = AVSpeechSynthesisVoice.speechVoices().sorted(by: {
        Locale.current.localizedString(forLanguageCode: $0.language)! < Locale.current.localizedString(forLanguageCode: $1.language)!
    })