how to get user selection in UIPickerView and use it else where? - arrays

all i want to do is change the values of min avg and max based on what the user selected in the picker menu so that i can use them in the MinC AvgC and MaxC label calculation. for example, if user selected a1 then min = 10, avg = 15, and max = 20, but if user selects a2 i want min to = 20, avg = 25, and max = 30. please help and thank you. your time, effort, and support are appreciated. bellow is my code which is currently working without any errors:
class ViewController: UIViewController, UIPickerViewDelegate, UITextFieldDelegate{
#IBOutlet var PLabel: UILabel!
#IBOutlet weak var C: UITextField!
#IBOutlet var MinC: UILabel!
#IBOutlet var AvgC: UILabel!
#IBOutlet var MaxC: UILabel!
var min = 0
var avg = 0
var max = 0
var P = ["a1","a2","a3","a4"]
var CFiller = ["0"]
override func viewDidLoad()
{super.viewDidLoad()
PLabel.text = P[0]
MinC.text = CFiller[0]
AvgC.text = CFiller[0]
MaxC.text = CFiller[0]
C.keyboardType = UIKeyboardType.NumberPad}
override func didReceiveMemoryWarning()
{super.didReceiveMemoryWarning()}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int
{ return 1}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int
{return P.count}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String?
{return P[row]}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
{ var PSelected = P[row]
PLabel.text = PSelected}
#IBAction func CalcButton(sender: AnyObject)
{if let ic = Int (C.text!)
{MinC.text = "\(min * ic)"
AvgC.text = "\(avg * ic)"
MaxC.text = "\(max * ic)"}}
}

Seems to me like you just need to use a switch statement to achieve your goal.
This could look something like this:
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
{ var PSelected = P[row]
PLabel.text = PSelected
switch PSelected {
case "a1":
min = 10
avg = 15
max = 20
case "a2":
min = 20
avg = 25
max = 30
...
default:
break
}
}
You could also set it up more efficiently if you desire, like this:
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
{ var PSelected = P[row]
PLabel.text = PSelected
var increment = 10
min = 10
avg = 15
max = 20
min += increment*row //if a1, then row == 0, so nothing is added
avg += increment*row
max += increment*row
}

Related

How do I loop back to the first item in an Array?

I'm sure this is very simple, but I'm using a button to go to the next item in an array and display it in a label. That much works just fine, however once the end of the array is reached the app crashes since there are no items left to display. How do I get it to go back to the first item? I've tried an If statement but had no luck.
import UIKit
class ViewController: UIViewController {
var firstQuote = 0
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBOutlet weak var quotesLabel: UILabel!
var quotes = ["","Quote 1", "Quote 2", "Quote 3"]
#IBAction func nextButton(_ sender: UIButton) {
firstQuote = firstQuote + 1
quotesLabel.text = quotes[firstQuote]
}
}
This is the If Statement I tried
#IBAction func nextButton(_ sender: UIButton) {
if firstQuote < quotes.count{
firstQuote = firstQuote + 1
quotesLabel.text = quotes[firstQuote]
}
if firstQuote == quotes.count{
firstQuote = 0
quotesLabel.text = quotes[firstQuote]
}
}
A common solution is to use % (the remainder operator) to wrap firstQuote back to 0 when it is equal to quotes.count:
firstQuote = (firstQuote + 1) % quotes.count
This works for me😁
class ViewController: UIViewController {
var quotes = ["Quote 0","Quote 1", "Quote 2", "Quote 3"]
var quotesNum = 0
#IBOutlet weak var result: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
result.text = quotes[quotesNum]
}
#IBAction func incrementButton(_ sender: Any) {
if quotesNum < quotes.count {
quotesNum += 1
if quotesNum == quotes.count {
quotesNum = 0
}
result.text = quotes[quotesNum]
}
}
With This Code Beside Fixing Your Problem, You Can Understand How property observer Can Work
class ViewController: UIViewController {
var quotes = ["Quote 0","Quote 1", "Quote 2", "Quote 3"]
var quotesNum: Int = 0 {
didSet {
result.text = quotes[quotesNum]
}
}
#IBOutlet weak var result: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
result.text = quotes[quotesNum]
}
#IBAction func incrementButton(_ sender: Any) {
if quotesNum < quotes.count - 1 {
if quotesNum == quotes.count - 1 {
quotesNum = 0
} else {
quotesNum += 1
}
} else {
quotesNum = 0
}
}

Receiving errors on 'UIPickerView' func settings

I have two (or more) text fields in an app, and I want each textField to pop up its own Pickerview wheel when selected... Here's what I've got so far:
var pickerView = UIPickerView()
#IBOutlet weak var serviceType: UITextField!
#IBOutlet weak var brandsField: UITextField!
var serviceArray = ["Services", "..."]
var brandsArray = ["Apple", "Samsung"]
override func viewDidLoad() {
super.viewDidLoad()
pickerView.delegate = self
pickerView.dataSource = self
}
func updatePicker(){
self.pickerView.reloadAllComponents()
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if serviceType.isFirstResponder{
return serviceArray.count
} else if brandsField.isFirstResponder{
return brandsArray.count
}
} //ERROR HERE
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if serviceType.isFirstResponder{
return serviceArray[row]
}else if brandsField.isFirstResponder{
return brandsArray[row]
}
} //ERROR HERE
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if serviceType.isFirstResponder{
let itemselected = serviceArray[row]
serviceType.text = itemselected
}else if brandsField.isFirstResponder{
let itemselected = brandsArray[row]
brandsField.text = itemselected
}
}
}
but it keeps giving me the error saying "Missing return in a function expected to return String?" and "Missing return in a function expected to return int" at where I've Commented. What can I do?
You can use this UITextField subclass if you want to use multiple textfields with pickerview.
class PickerTextField: UITextField,UIPickerViewDelegate,UIPickerViewDataSource {
let pickerView = UIPickerView()
var itemList = [String]()
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
#objc func textEdited(_ sender:PickerTextField)
{
self.text = itemList[pickerView.selectedRow(inComponent: 0)]
}
override func draw(_ rect: CGRect) {
super.draw(rect)
self.tintColor = UIColor.clear
self.addTarget(self, action: #selector(textEdited(_:)), for: .editingChanged)
pickerView.showsSelectionIndicator = true
pickerView.delegate = self
pickerView.dataSource = self
self.inputView = pickerView
let toolBar = UIToolbar()
toolBar.barStyle = UIBarStyle.default
toolBar.isTranslucent = true
toolBar.tintColor = .black
toolBar.sizeToFit()
let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(doneBtnAction(_:)))
let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(doneBtnAction(_:)))
toolBar.items = [cancelButton, spaceButton, doneButton]
self.inputAccessoryView = toolBar
}
#objc func doneBtnAction(_ sender:UIBarButtonItem) {
resignFirstResponder()
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return itemList.count
}
func pickerView(_ pickerView: UIPickerView, attributedTitleForRow row: Int, forComponent component: Int) -> NSAttributedString? {
let title = itemList[row]
return NSAttributedString(string: title, attributes: [NSAttributedStringKey.foregroundColor:UIColor.black])
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
self.text = itemList[row]
}
}
And assign the options list in viewDidLoad
class ViewController: UIViewController {
#IBOutlet weak var serviceType: PickerTextField!
#IBOutlet weak var brandsField: PickerTextField!
override func viewDidLoad() {
super.viewDidLoad()
serviceType.itemList = ["Services", "others"]
brandsField.itemList = ["Apple", "Samsung"]
}
}
Assign subclass to textfield.
Result
You need to return the else case.
if serviceType.isFirstResponder{
return serviceArray.count
} else if brandsField.isFirstResponder{
return brandsArray.count
} else {
// insert your else case here
return 0 // for example
}
Refactor these 3 methods to this , as the compiler won't know what to return if all if cases are not hit , so it gives this error
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if serviceType.isFirstResponder{
return serviceArray.count
} else {
return brandsArray.count
}
} //ERROR HERE
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if serviceType.isFirstResponder{
return serviceArray[row]
}else {
return brandsArray[row]
}
} //ERROR HERE
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if serviceType.isFirstResponder{
let itemselected = serviceArray[row]
serviceType.text = itemselected
}else {
let itemselected = brandsArray[row]
brandsField.text = itemselected
}
}

how to add a column to pre-exisiting pickerview

I need a multiple component pickerview, but I need to add a new column to the far left of it. So far it only has two of the three I need. Here is the current code. I have addeded arrays, wrapped an array inside an array, added variables as a column and also changed the outputs.
import UIKit
class Country {
var cats: String
var country: String
var cities: [String]
init(country:String, cities:[String]) {
self.cats = cat
self.country = country
self.cities = cities
}
}
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet weak var pickerView: UIPickerView!
#IBOutlet weak var countryLbl: UILabel!
var countries = [Country]()
override func viewDidLoad() {
pickerView.delegate = self
pickerView.dataSource = self
cats.apppend(Cat(cat: "furry",
countries.append(Country(country: "India", cities: ["Delhi", "Ahmedabad", "Mumbai", "Pune"]))
countries.append(Country(country: "USA", cities: ["New York", "DC", "Fairfax"]))
countries.append(Country(country: "Austrailia", cities: ["Sydney", "Melbourne"]))
super.viewDidLoad()
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 3
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if component == 0 {
return countries.count
}
else {
let selectedCountry = pickerView.selectedRow(inComponent: 0)
return countries[selectedCountry].cities.count
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if component == 0 {
return countries[row].country
}
else {
let selectedCountry = pickerView.selectedRow(inComponent: 0)
return countries[selectedCountry].cities[row]
}
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
pickerView.reloadComponent(1)
let selectedCountry = pickerView.selectedRow(inComponent: 0)
let selectedCity = pickerView.selectedRow(inComponent: 1)
let country = countries[selectedCountry].country
let city = countries[selectedCountry].cities[selectedCity]
countryLbl.text = "Country: \(country)\nCity: \(city)"
}
}
I added the vars but do I add more brackets and then I don't know how to identify the self like why does country = country but cat can't = cat? Also, the first column I'm going to add (far left in the row) will only have 2 choices and won't effect the other choices.
Since the cats component has nothing to do with the countries, do not add cats to your Countries class (which should be a struct, by the way).
Just have a separate cats array in your view controller. And you need to update all of the picker view methods.
struct Country {
let country: String
let cities: [String]
}
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet weak var pickerView: UIPickerView!
#IBOutlet weak var countryLbl: UILabel!
let cats = ["Cat1", "Cat2"]
var countries = [Country]()
override func viewDidLoad() {
pickerView.delegate = self
pickerView.dataSource = self
countries.append(Country(country: "India", cities: ["Delhi", "Ahmedabad", "Mumbai", "Pune"]))
countries.append(Country(country: "USA", cities: ["New York", "DC", "Fairfax"]))
countries.append(Country(country: "Austrailia", cities: ["Sydney", "Melbourne"]))
super.viewDidLoad()
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 3
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if component == 0 {
return cats.count
} else if component == 1 {
return countries.count
} else {
let selectedCountry = pickerView.selectedRow(inComponent: 1)
return countries[selectedCountry].cities.count
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if component == 0 {
return cats[row]
} else if component == 1 {
return countries[row].country
} else {
let selectedCountry = pickerView.selectedRow(inComponent: 1)
return countries[selectedCountry].cities[row]
}
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if component == 0 {
// do something with the new cat
} else if component == 1 || component == 2 {
if component == 1 {
pickerView.reloadComponent(2)
}
let selectedCountry = pickerView.selectedRow(inComponent: 1)
let selectedCity = pickerView.selectedRow(inComponent: 2)
let country = countries[selectedCountry].country
let city = countries[selectedCountry].cities[selectedCity]
countryLbl.text = "Country: \(country)\nCity: \(city)"
}
}
}

How to have two variables depending on each other

I have this problem: I have two text fields, one pickerView containing an array and another text field where you need to put in a specific code depending on the selection you made in the pickerView to be able to press the button. This is what I got
var SchoolsArray = ["Option 1",
"Option 2",
"Option 3",
"Option 4"]
var code1 = "zxy" // code for Option 1
var code2 = "gbv" // code for Option 2
var code3 = "jwn" // code for Option 3
var code4 = "hqc" // code for Option 4
#IBOutlet weak var firstNameTxtField: UITextField!
#IBOutlet weak var schoolNameTxtField: UITextField!
#IBOutlet weak var schoolCodeTxtField: UITextField!
#IBAction func createAccountBtnPressed(_ sender: Any) {
if firstNameTxtField.text != nil && schoolNameTxtField.text != nil && schoolCodeTxtField.text != nil {
if schoolNameTxtField.text == "Option 1" && schoolCodeTxtField.text == code1 {
//do something here
} else {
}
} else {
}
}
As you can see this only works if you select Option 1. How can I make this work so if you select "Option 1" and in schoolCodeTxtField put in "zxy" it will proceed and if you select "Option 2" and put in "gbv" it will also proceed and so on. I hope you understand what I mean. I appreciate all help
Just like SchoolArray, you can use an array for the codes as well, and use following method:
var CodesArray = ["zxy", "gbv", "jwn", "hqc"]
#IBAction func createAccountBtnPressed(_ sender: Any) {
guard
firstNameTxtField.text != nil,
let option = schoolNameTxtField.text,
let index = SchoolsArray.index(where: { $0 == option }),
CodesArray[index] == schoolCodeTxtField.text
else {
return
}
// Code & Option both matched
}
How about use a dictionary that contains your options as keys and your codes as values. Something like this:
var SchoolsOptions = ["Option 1": "zxy",
"Option 2": "gbv",
"Option 3": "jwn",
"Option 4": "hqc"]
#IBAction func createAccountBtnPressed(_ sender: Any) {
if firstNameTxtField.text != nil && schoolNameTxtField.text != nil && schoolCodeTxtField.text != nil {
for (option, code) in SchoolsOptions {
if schoolNameTxtField.text == option && schoolCodeTxtField.text == code {
//do something here
// You only get here if the option and code match for that given school. If you need specific logic for each school you'll have to check which option you're on.
}
}
} else {
}
}
This is the cleanest solution I can think of right off the bat.
#IBOutlet weak var firstNameTxtField: UITextField!
#IBOutlet weak var schoolNameTxtField: UITextField!
#IBOutlet weak var schoolCodeTxtField: UITextField!
var codeArray: [String] = [
"zxy",
"gbv",
"jwn",
"hqc"
]
var selectedCode: String!
override func viewDidLoad() {
super.viewDidLoad()
setupPickerViewAndAssignItsDelegateAndDatasource()
guard let selectedCode = codeArray.first else { return }
self.selectedCode = selectedCode
}
public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return codeArray.count
}
public func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return "Option \(row + 1)"
}
public func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
selectedCode = codeArray[row]
}
#IBAction func createAccountBtnPressed(_ sender: Any) {
if firstNameTxtField.text != nil && schoolNameTxtField.text != nil && schoolCodeTxtField.text != nil {
if schoolNameTxtField.text == selectedCode {
//do something here
} else {
}
} else {
}
}

Swift PickerView does not show array elements

My "picker2" pickerview does not show data from "modelArray" array. When I dup the array I have data in it. But no data shown in pickerview at all.
I did everything on mind and did my research how to do it. But no success.
Any help will be highly appreciated :)
import UIKit
class MakeViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {
#IBOutlet weak var txt_make: UITextField!
#IBOutlet weak var txt_model: UITextField!
var makeArray = [String]()
var modelArray = [String]()
var picker = UIPickerView()
var picker2 = UIPickerView()
var numberOfRowsMake = 0
var numberOfRowsModel = 0
override func viewDidLoad() {
super.viewDidLoad()
picker.delegate = self
picker.dataSource = self
picker2.delegate = self
picker2.dataSource = self
txt_make.inputView = picker
txt_model.inputView = picker2
txt_make.clearButtonMode = .Always
txt_model.clearButtonMode = .Always
parseJSON2()
}
func parseJSON2() {
let path : String = NSBundle.mainBundle().pathForResource("json2", ofType: "json")! as String
let jsonDATA = NSData(contentsOfFile: path) as NSData!
numberOfRowsMake = readableJSON["Cars"].count
for var i = 0; i < numberOfRowsMake; ++i {
let make = readableJSON["Cars"][i]["Manufacturer"].stringValue
makeArray.append(make)
}
}
func parseJSON3() {
let path : String = NSBundle.mainBundle().pathForResource("json2", ofType: "json")! as String
let jsonDATA = NSData(contentsOfFile: path) as NSData!
numberOfRowsMake = readableJSON["Cars"].count
for var i = 0; i < numberOfRowsMake; ++i {
let make = readableJSON["Cars"][i]["Manufacturer"].stringValue
let model = readableJSON["Cars"][i]["Model"].stringValue
print(txt_make.text)
if make == txt_make.text {
modelArray.append(model)
}
}
dump(modelArray)
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView == picker {
return numberOfRowsMake
}
if pickerView == picker2 {
return numberOfRowsModel
}
return 1
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if pickerView == picker {
txt_make.text = makeArray[row]
}
if pickerView == picker2 {
self.picker2.reloadAllComponents()
parseJSON3()
txt_model.text = modelArray[row]
}
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView == picker {
return makeArray[row]
}
if pickerView == picker2 {
return modelArray[row]
}
return ""
}
}
Here is the local JSON file.
{
"Cars" :
[{
"Manufacturer": "ABARTH1",
"Model": "500, 2012 onwards",
}, {
"Manufacturer": "ABARTH1",
"Model": "500, 2012 onwards",
}, {
"Manufacturer": "ABARTH1",
"Model": "500, 2012 onwards",
}, {
"Manufacturer": "ABARTH2",
"Model": "500, 2012 onwards",
}, {
"Manufacturer": "ABARTH2",
"Model": "500, 2012 onwards",
}, {
"Manufacturer": "ABARTH2",
"Model": "500, 2012 onwards",
}
]
}

Resources