uipickerview index out if range - ios

I'm trying to learn to code Swift and recently I faced a bug which is so embarrassing.
I have 2 textfield which both are connected to a picker view.
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if EntCity.isEditing
{
return MainCities[row].name
}
return MainJ[row].name
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if EntState.isFirstResponder
{
EntState.text = MainJ[row].name
Global_Addresses.global_address.cityID_fromState = MainJ[row].id
GetCities()
}
if EntCity.isEditing
{
if (EntState.text?.isEmpty)!
{
DispatchQueue.main.async {
self.DisplayMessage(UserMessage: "ابتدا استان را انتخاب کنید")
}
}
else
{
EntCity.text = MainCities[row].name
Global_Addresses.global_address.smallCityID = MainCities[row].id
}
}
EntState.text = MainJ[row].name
Global_Addresses.global_address.cityID_fromState = MainJ[row].id
GetCities()
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return MainCities.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return MainCities[row].name
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
EntCity.text = MainCities[row].name
Global_Addresses.global_address.smallCityID = MainCities[row].id
print("?????????????????????")
print(Global_Addresses.global_address.smallCityID)
}
}
the code works fine and both textfield can show the data in the picker view to choose. these textfield are connected, it means that
you have to choose one of the rows in textfield number 1 to get the data for textfield number 2 . when i choose the first data , and select the second textfield to choose the second one , it works fine untill i choose of those data which their row number is bigger than the first textfield
and as you can see i have declared that if it select first or second textfield to return different number for row!

Related

UIPickerView get selected value without datasource

What would be the best way to get the value from a PickerView without having a datasource? So i can not read values from i.e. an array.
Current values are just row numbers, that i need to read after user is done with picking.
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 3
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if component == 0 {
return 300
} else {
return 10
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if component == 0 {
return "\(row)."
} else {
return "\(row)"
}
}
You can use pickerView.selectedRow(inComponent:)
let firstValue = pickerView.selectedRow(inComponent: 0)
let secondValue = pickerView.selectedRow(inComponent: 1)
Both will just be an Int value representing the currently selected row index in it's respective component. And since your values are starting from 0, you can use the values directly.
You simply add this func:
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
print(row)
}
Just take care that row starets at 0

for loop in titleForRow in pickerView not working

I was creating a clock pickerView and used the following:
var countSec = Array(0...10)
var countMin = Array(0...59)
var countHour = Array(0...59)
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if component == 0{
for count in countSec {
return "\(count)"
}
}else{
for count in countMin{
return "\(count)"
}
}
return nil
}
But when I run, all the data was 0s.
Don't use loops in titleForRow. Just return the appropriate value for the requested row.
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if component == 0 {
return "\(countSec[row])"
} else {
return "\(countMin[row])"
}
}

number input with UiPickerView

In my use case I would like to add in numbers consisting of 4 digits, like in the image. The first digit should be 0 or 1.
My code so far is:
func numberOfComponents(in weightPickerView: UIPickerView) -> Int {
return 4
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return loopingMargin * numbers.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return numbers[row % numbers.count]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
digits[component] = row % numbers.count
let weightString = "\(digits[0])\(digits[1])\(digits[2])\(digits[3])"
weightField.text = weightString
}
How can I achieve that?
Considering:
let numbers = [2,10,10,10]
var digits = [0,0,0,0]
Update your delegate methods like this:
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return numbers[component]
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return String(row)
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
digits[component] = row
let weightString = "\(digits[0])\(digits[1])\(digits[2])\(digits[3])"
weightField.text = weightString
}
You can try
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if(component == 0)
{
return 2
}
else
{
return loopingMargin * numbers.count
}
}

I can't add a UIPickerview for gender in a registration form

I am creating a registration form and I have to include the gender inside a text field using a picker view. However, I am getting question marks instead of male and female.
Here is my code:
#IBOutlet weak var genderfield: UITextField!
let pickerView = UIPickerView()
let gender1 = ["Male", "Female"]
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return gender1.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return gender1[row]
}
func pickerView(_ pickerView:UIPickerView,didSelectRow row: Int,forComponent component: Int){
genderfield.text = gender1[row]
genderfield.resignFirstResponder()
}
And in ViewDidLoad:
pickerView.delegate = self
pickerView.dataSource = self
genderfield.inputView = pickerView
I don't think there is something wrong in my code. I have been googling for hours.
You get question marks because you have the wrong signature on your titleForRow delegate method.
Change:
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return gender1[row]
}
to:
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return gender1[row]
}
Note the addition of _ just after the (.
You can not added UIPickerViewDelegate, UIPickerViewDataSource.
so when you add delegate and data source of picker view its work fine.
like this:
extension RegisterVC : UIPickerViewDelegate, UIPickerViewDataSource{
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return gender1.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return gender1[row]
}
func pickerView(_ pickerView:UIPickerView,didSelectRow row: Int,inComponent component: Int){
genderfield.text = gender1[row]
genderfield.resignFirstResponder()
}

UIPickerView depending on first component

So I have a UIPickerView with two components. The first one called "Cupboards", the second "Drawer". They have a one to many relationships in CoreData Cupboards <-->> Drawer. I would like that if I select a Cupboard, only the matching Drawers get displayed. I'm not sure how to get that working with the relationship.
That's what I have for showing the Cupboard:
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 2
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if(component==0){
return cupboards.count
}
xxxx
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if(component==0){
return cupboards[row].name
}
xxxx
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if(component==0){
}
}
Thank you in advance
Update:
Got it like that now, but I get no results.
var cupboardDrawers = [Drawer]()
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if(component==0){
let request: NSFetchRequest<Drawer> = Drawer.fetchRequest()
request.predicate = NSPredicate(format: "cupboard == %#", cupboards[row].name!)
do{
let result = try mgdContext.fetch(request)
cupboardDrawers = result
addEatDataPicker.reloadAllComponents()
}catch{
print(error.localizedDescription)
}
}
}
You need to create and update a cupboardDrawers array with the fetching results:
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 2
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if(component==0){
return cupboards.count
} else {
return cupboardDrawers.count
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if(component==0){
return cupboards[row].name
} else {
return cupboardDrawers[row].yourProperty
}
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if(component==0){
// you can add this part to a separate function and call it here
cupboardDrawers = []
let request = NSFetchRequest<Drawer>(entityName:”Drawer”)
request.predicate = YourPredicate with cupboards[row].name
do {
let items = context.fetch(request)
guard items.count > 0 else {
print(“no items found”)
return
}
cupboardDrawers = items
//reload your picker
} catch {
print(error)
}
}
}

Resources