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

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}"

Related

Get list of countries from AVSpeechSynthesisVoice

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 ?? ""))"
}

Create a warning based on UIPickerViewSelection

So here is what I am trying to do.
I am working on an app that allows the company I work for to see what account number they should use when making a purchase. There are certain locations where the costs should be split to different accounts based on location, but they are only for a certain few. I would like to issue a warning in the form of a popup, which I already have coded. My thought process is that I can use if/else statements to issue what I need, but I am unsure as to how to word it. It would supply a regular account number if the accounts need not be split, but then a warning statement if it did. The code is below. My problem is under the didSelectRow.
What's not actually shown is the PopUpVC I am using and the full list of array data because it's long.
Much thanks to this website as it has really helped me code my first project!
let account: [Account] = [Account(number: 0, description: "SELECT")]
//there is actually more data here but I am taking it out so it's shorter
let tasks: [Task] = [Task(number: 0, description: "SELECT")]
//there is actually more data here but I am taking it out so it's shorter
let locations: [Location] = [Location(number: 0, description: "SELECT")]
//there is actually more data here but I am taking it out so it's shorter
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 3
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if component == accountsComponent {
return account.count
} else if component == tasksComponent {
return tasks.count
} else if component == locationsComponent {
return locations.count
}
return 0
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if component == accountsComponent {
return account[row].description
} else if component == tasksComponent {
return tasks[row].description
} else if component == locationsComponent {
return locations[row].description
}
return nil
}
func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
if component == accountsComponent {
let label = (view as? UILabel) ?? UILabel()
label.font = label.font.withSize(12)
label.textAlignment = .center
label.text = account[row].description
return label
}
if component == tasksComponent {
let label = (view as? UILabel) ?? UILabel()
label.font = label.font.withSize(12)
label.textAlignment = .center
label.text = tasks[row].description
return label
}
if component == locationsComponent {
let label = (view as? UILabel) ?? UILabel()
label.font = label.font.withSize(12)
label.textAlignment = .center
label.text = locations[row].description
return label
} else {
let label = (view as? UILabel) ?? UILabel()
label.font = label.font.withSize(10)
label.textAlignment = .center
label.text = account[row].description
return label
}
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
pickerView.reloadAllComponents()
let selectedAccount = pickerView.selectedRow(inComponent: 0)
let selectedTask = pickerView.selectedRow(inComponent: 1)
let selectedLocation = pickerView.selectedRow(inComponent: 2)
let ACCOUNTS = account[selectedAccount].description
let TASKS = tasks[selectedTask].description
let LOCATION = locations[selectedLocation].description
let ACCOUNTSNUMBER = account[selectedAccount].number
let TASKSNUMBER = tasks[selectedTask].number
let LOCATIONNUMBER = locations[selectedLocation].number
if pickerView.selectedRow(inComponent: 2) = 10 //this is what I am unsure of how to do {
textViewInput = "WARNING - this should be split"
}
else {
textViewInput = "\(ACCOUNTSNUMBER) \(TASKSNUMBER) \(LOCATIONNUMBER)"
}
I prefer switch statements over a long series of if-else if-else statements. I would personally do something like this:
switch pickerView.selectedRow(inComponent: 2) {
case 10, 11, 12:
present(popUpVc, animated: true)
default:
textViewInput = "\(ACCOUNTSNUMBER) \(TASKSNUMBER) \(LOCATIONNUMBER)"
}
In this case, you would replace what I put as 10, 11, 12 as whatever rows you determine that need to have the accounts split. I'm also assuming here that PopUpVC is a UIAlertController that you are using to display the warning to the user.

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"))

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()
}
}