Get list of countries from AVSpeechSynthesisVoice - swift

I'm trying to get the Region Code found in AVSpeechSynthesisVoice instead of e.g: en-GB.
The output I'm aiming for is as follow
This is my current code, while it works, I feel there must be a more elegant solution and from what I read, split by - could product errors for some languages
let speechVoices = AVSpeechSynthesisVoice.speechVoices()
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 regionCodeArray = languageCode.split(separator: "-") // FIXME: buggy may break
let regionCode = regionCodeArray.removeLast()
// Must be a more elegant way to get RegionCode
let country = Locale.current.localizedString(forRegionCode: String(regionCode))
return "\(language) (\(country ?? ""))"
}
Thanks!

So I thought of another alternative that doesn't require splitting and this is what I got, but I welcome alternative answers or perhaps a comment on my code as I am learning and looking to improve
let speechVoices = AVSpeechSynthesisVoice.speechVoices()
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 ?? ""))"
}

Related

How to add a special character in a UIPicker view of integers

Still Learning swift
What Im trying to do is add a "°C" and "°F"
after an integer, I have a created and array of ints and gave them a specific range
that should be in the pickerView, I got the values to display Im just struggling with how I could get that "special char " to display after the integer
I was thinking of maybe creating a for loop and load in the the values like that and append the "°C" and "°F" using the unicode scalar.
I was wondering if anyone has any recommendations of how i could get this done ?
class tempConversionTabViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {
var celsius: [Int] = []
var fahrenheitTemps: [Int] = []
override func viewDidLoad() {
super.viewDidLoad()
fahrenheitTemps += -129...134
celsius += -90...57
// for fahrenheitTemps in -129...134{
// tempPicker.append
//}
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
switch
segmentControl.selectedSegmentIndex{
case 0:
return fahrenheitTemps.count
default:
return celsius.count
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int , forComponent component: Int) -> String?{
switch segmentControl.selectedSegmentIndex {
case 0:
var selected = fahrenheitTemps[tempPicker.selectedRow(inComponent: 0)]
selected = (selected - 32) * 5/9
convertedLabel.text = String("\(selected) \u{2103}")
let myString = fahrenheitTemps.map { String($0)}
return myString[row]
default:
var selected = celsius[tempPicker.selectedRow(inComponent: 0)]
selected = (selected * 9/5) + 32
convertedLabel.text = String("\(selected) \u{2109}")
let myString = celsius.map { String($0)}
return myString[row]
}
}
Image of how I want it to display
Just use string concatenation to add the character:
Change:
return myString[row]
to:
return myString[row] + "\u{2109}"

swift - How sort alphabetically annotations array

My project is a map with a lot of annotations points, and user could look for a specific annotation thanks to a pickerView. All is fine except the list of all annotations points seems randomly displayed. I would like to sort the annotations alphabetically.
Here s my current working code :
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return self.mapView.annotations[row].title ?? "No title"
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
self.mapView.selectAnnotation(self.mapView.annotations[row], animated: true)
}
I ve tried to implement this, but without any success...
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
let sortedNames = self.mapView.annotations.sorted(by: {$0.title < $1.title})
return sortedNames[row].title ?? "No title"
}
I ve got this error:
Cannot convert value of type 'String??' to expected argument type
'UIContentSizeCategory'
Any hint would be greatly appreciated.
I'm aware this question is a bit old to answer but for anyone else having the issue the problem is that the String can not be optional. The fix it to either provide a default value or force unwrap it. For example this would be one solution to the question:
let sortedNames = self.mapView.annotations.sorted(by: { ($0.title ?? "") < ($1.title ?? "") }))
return sortedNames[row].title ?? "No title"
I've just had exactly this error when trying to sort an array of a different class by a string property. The problem appears to be that the property you are sorting by is optional. Using a non-optional property works as expected, using an optional property gives the somewhat bizarre 'UIContentSizeCategory' error.
Something like this should do what you need:
let sorted = self.mapView.annotations { (a1, a2) -> Bool in
if let s1 = a1.title {
if let s2 = a2.title {
return s1 > s2
}
}
return false
}

Accessing information from another viewController

I am new to swift and I am trying to repopulate a pickerview using an array of names from another class. I have this class Notes that creates notes and each note has a name/title, I am trying to access those names/title and put them in pickerview, can anyone help me.
import UIKit
var allNotes: [Note] = []
var currentNoteindex: Int = -1
var noteTable: UITableView?
let kAllNotes:String = "notes"
class Note: NSObject
{
var date:String
var note:String
var name:String
override init()
{
date = NSDate().description
name = ""
note = ""
}
func dictionary() -> NSDictionary
{
return ["note": note, "date": date, "name": name]
}
I have two different pickerview and one works it's just the one with the names doesn't work.
override func viewDidLoad()
{
super.viewDidLoad()
fileNamePicker.dataSource = self
fileNamePicker.delegate = self
gradePicker.dataSource = self
gradePicker.delegate = self
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int
{
if pickerView == gradePicker
{
return grades.count
}
else
{
return allNotes.count
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String?
{
if pickerView == gradePicker
{
return grades[row]
}
else
{
//This is where the Problem is, but I don't know how to fix it.
let nameFiles = allNotes[currentNoteindex].name
return nameFiles[row]
}
}
func numberOfComponents(in pickerView: UIPickerView) -> Int
{
return 1
}
nameFiles is accessing a name from a note.
nameFiles[row] doesn't work because nameFiles is not an array.
If you want to return a string, simply do return nameFiles. Check first to make sure that nameFiles actually has a value, though!
Looks like your allNotes array is empty. You have initilaize but does not seems to append the object. Create initiliaze method inside Note class
init(_ date: String, note: String, name: String) {
self.date = date
self.note = note
self.name = name
}
In your viewcontroller class try appending like this. Now below you can access inside picker view method:-
//You can append by doinf iteration based on your data
allNotes.append(Note(date: "value1", note: "Value", name: "name"))

Json parsing into swift 3 currency exchange values from bank accounts

Is it possible to fetch currency exchange rates from some banks websites in my country, and is it legal ?
making an app specified to my country and have been trying for a week now but couldn't find an answer this is the code could you tell a solution?
import UIKit
class ViewController: UIViewController,UIPickerViewDelegate,UIPickerViewDataSource {
#IBOutlet weak var lblDisplay: UILabel!
#IBOutlet weak var txtField: UITextField!
#IBOutlet weak var pkrView: UIPickerView!
var myCurrency:[String] = []
var myValue:[Double] = []
var activeCurrency:Double = 0
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: "http://ca-egypt.com")
let task = URLSession.shared.dataTask(with: url!) { (data, response, error)in
if error != nil{
print("error is here!")
}else{
if let content = data{
do{
let myJson = try JSONSerialization.jsonObject(with: content, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject
if let rates = myJson["rates"] as? NSDictionary{
var firstOne = true
for (key,value)in rates{
self.myCurrency.append((key as? String)!)
self.myValue.append((value as? Double)!)
}
}
}catch{
}
}
}
self.pkrView.reloadAllComponents()
}
task.resume()
}
#IBAction func btnCalculateAction(_ sender: UIButton) {
lblDisplay.text = String(Double(txtField.text!)! * activeCurrency)
}
func numberOfComponents(in pickerView: UIPickerView,umberOfRowsInComponent component: Int) -> Int {
return myCurrency.count
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return myCurrency.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return myCurrency[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
activeCurrency = myValue[row]
}
}
Image of the Error:
Hello #Ali instead of fetching currency exchange rates from some banks websites, you can make use of some API, which are freely available or you can make use of paid API's. And off-course fetching currency exchange rates is illegal. They won't allow some-one to get values.
To get various countries currency-exchange rates use Fixer.io , which are updating on daily basis, and yes it is freely available.
Fixer.io is a free JSON API for current and historical foreign exchange rates, published by the European Central Bank. The rates are updated daily around 4PM CET.
Example :
API Link : http://api.fixer.io/latest?base=USD
Alamofire.request("http://api.fixer.io/latest?base=USD") .responseJSON { response in
if let arr = response.result.value as? [String:AnyObject]
{
let usd_val = (arr["rates"]?["INR"] as? NSNumber)!
print(usd_val)
}
}
By this way you can parse JSON API and use this currency exchange values, and if you want to get your country currency exchange value, then pass value.
example : To get current currency exchange value of Japan, then pass value of it. Like this. http://api.fixer.io/latest?base=JPY
Hope it helps you.

Issue saving PFobjects into an array when using pickerView

i'm relatively new to Swift. I've encountered an issue when using PFQuery in pickerView.
I'm trying to implement a 2 component pickerView as demonstrated below:
Component 0: Component 1
"A": "Altivo", "Altrez"
"B": "Beverly", "Bijou"
Choosing "A" from Component 0 will show "Altivo", "Altrez" in Component 1
The values from Component 1 are queried from Parse by using the value from Component 0
Here's my code:
var condoNameList: [String] = [String]()
var condoPicker = UIPickerView()
var condoAlphabet: [String] = [String]()
private let prefixComponent = 0
private let condoNameComponent = 1
override func viewDidLoad() {
super.viewDidLoad()
condoAlphabet = ["A", "B"]
}
//Start: For condoName picker
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 2
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if component == prefixComponent{
return condoAlphabet.count
}else {
return self.condoNameList.count
}
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if component == prefixComponent {
condoNameList.removeAll()
let query = PFQuery(className: "condodirectory")
let selectedalphabet: String = condoAlphabet[row] as String!
query.whereKey("condoName", hasPrefix: selectedalphabet)
query.findObjectsInBackgroundWithBlock{
(objects:[PFObject]?, error:NSError?)->Void in
if error == nil{
for object in objects!{
//print(object)
let condoName:String = object["condoName"] as! String
self.condoNameList.append(condoName)
}
}
//print("condo Name List is \(self.condoNameList)") //Position 1
}
print("condo Name List is \(self.condoNameList)") //Position 2
condoPicker.reloadComponent(condoNameComponent)
condoPicker.selectRow(0, inComponent: condoNameComponent, animated: true)
}
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if component == prefixComponent{
return condoAlphabet[row]
}else {
return self.condoNameList[row]
}
}
The issue is at Position 1, the print function is able to print out the condoNameList but at Position 2 it prints an empty array. As a result, the list for Component 1 is not showing up in the PickerView.
Anyone knows why?
Thanks in advance for the help.
I managed to solve the problem from another thread by using the didset{} method.
var condoNameList: [String] = [] {
didSet {
self.condoNameListTemp = condoNameList
condoName.inputView = condoPicker
condoPicker.reloadAllComponents()
}
}