Multiple UIPickerViews in IOS5 app - ios

I started learning iOS programming about two months ago and so far I love it, but I'm kinda struggling a bit with UIPicker(s) and UIDatePickers in the app that I'm making, and I was hoping that someone might point me in the right direction. The app is supposed to mimic already existing PHP web app, that is nothing more than a form with a bunch of dropdowns.
Lets say that i have GetAddressViewController that will have a bunch of input fields. For the sake of simplicity lets say that I will have only 3 input fields for: country, city and street.
The user should tap on "country" input field and the UIPicker shows up much like a keyboard would and after selecting the country, a web app will return a JSON array with all the cities of that country. The same process is repeated when user taps on "city" input field, the UIPicker pops up with a list of returned cities, user selects a street, the UIPicker slides out and web app returns an array of streets etc.
Lets say that in my In my GetAddressViewController.h file i have:
#import <UIKit/UIKit.h>
#interface GetAddressViewController : UIViewController
{
UITextField *countryField;
UITextField *cityField;
UITextField *streetField;
NSArray *countries;
NSArray *cities;
NSArray *streets;
}
#property(nonatomic, strong) IBOutlet UITextField *countryField;
#property(nonatomic, strong) IBOutlet UITextField *cityField;
#property(nonatomic, strong) IBOutlet UITextField *streetField;
#property(nonatomic, strong) IBOutlet NSArray *countries;
#property(nonatomic, strong) IBOutlet NSArray *cities;
#property(nonatomic, strong) IBOutlet NSArray *streets;
#end
In GetAddressViewController.m file i have synthesized properties and in the storyboard i only have 3 input fields that have been connected to appropriate outlets.
Is there some fundamental mistake in my existing code that i should be aware of?
Now, I feel that I have missed something while reading the tutorials regarding picker views, since most of the examples that I've found on StackOverflow don't make much sense to me.
Could someone point me to a basic similar example that could help me. Are UIPickers the way to go or is there a better approach?
I haven't felt this helpless for a while and any help would be greatly appreciated, thanks
EDIT:
Ok I'm making progress I hope that I can help someone else who has the same problem.
To make this work and to connect pickerview to input fileds inputView property you need to do this.
To your .h file you need to add two delegates: UIPickerViewDelegate and UIPickerViewDataSource
#interface ViewController : UIViewController<UIPickerViewDelegate, UIPickerViewDataSource>{ ...
Then in your .m file you'll need to have something like this. I have this code in my wiewDidLoad method.
UIPickerView *cityPicker = [[UIPickerView alloc] initWithFrame:CGRectZero];
cityPicker.delegate = self;
cityPicker.dataSource = self;
[cityPicker setShowsSelectionIndicator:YES];
cityField.inputView = cityPicker;
This simply means that cityPicker pickerview will appear when you tap on the cityField.After that you need to add the following pickerview delegate methods that will fill pickerview with correct data. The data in my case is an array that holds a list of cities.
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return cities.count;
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
return [cities objectAtIndex:row];
}
- (void) pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
cityField.text = (NSString *)[cities objectAtIndex:row];
}
If you want to have "Done" that will hide the UIPicker you'll need this code:
UIToolbar* mypickerToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 56)];
mypickerToolbar.barStyle = UIBarStyleBlackOpaque;
[mypickerToolbar sizeToFit];
NSMutableArray *barItems = [[NSMutableArray alloc] init];
UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
[barItems addObject:flexSpace];
UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(pickerDoneClicked)];
[barItems addObject:doneBtn];
[mypickerToolbar setItems:barItems animated:YES];
cityField.inputAccessoryView = mypickerToolbar;
And add a new method pickerDoneClicked
-(void)pickerDoneClicked
{
NSLog(#"Done Clicked");
[cityField resignFirstResponder];
}
I hope that this may help someone.

Hi Please follow this whole solution of multiple pickerview or just use -(void)createActionsheet it may solve your problem
define in .h
UIActionSheet *actionSheet;
NSString *pickerType;
BOOL select
define in .m
-(IBAction)countryBtnPressed:(id)sender
{
[self createActionSheet];
pickerType = #"picker";
select = NO;
UIPickerView *chPicker = [[UIPickerView alloc] initWithFrame:CGRectMake(0.0, 44.0, 0.0, 0.0)];
chPicker.dataSource = self;
chPicker.delegate = self;
chPicker.showsSelectionIndicator = YES;
[actionSheet addSubview:chPicker];
Txt.text = [array objectAtIndex:0];
[chPicker release];
}
-(IBAction)stateBtnPressed:(id)sender
{
[self createActionSheet];
pickerType = #"statepicker";
select = NO;
UIPickerView *chPicker = [[UIPickerView alloc] initWithFrame:CGRectMake(0.0, 44.0, 0.0, 0.0)];
chPicker.dataSource = self;
chPicker.delegate = self;
chPicker.showsSelectionIndicator = YES;
[actionSheet addSubview:chPicker];
stateTxt.text = [stateArray objectAtIndex:0];
[chPicker release];
}
/// Create Action Sheet
- (void)createActionSheet {
if (actionSheet == nil) {
// setup actionsheet to contain the UIPicker
actionSheet = [[UIActionSheet alloc] initWithTitle:#"Select"
delegate:self
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:nil];
UIToolbar *pickerToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
pickerToolbar.barStyle = UIBarStyleBlackOpaque;
[pickerToolbar sizeToFit];
NSMutableArray *barItems = [[NSMutableArray alloc] init];
UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
[barItems addObject:flexSpace];
[flexSpace release];
UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(pickerDone:)];
[barItems addObject:doneBtn];
[doneBtn release];
[pickerToolbar setItems:barItems animated:YES];
[barItems release];
[actionSheet addSubview:pickerToolbar];
[pickerToolbar release];
[actionSheet showInView:self.view];
[actionSheet setBounds:CGRectMake(0,0,320, 464)];
}
}
#pragma mark UIPickerViewDelegate Methods
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
int count;
if ([pickerType isEqualToString:#"picker"])
count = [array count];
else if([pickerType isEqualToString:#"picker"])
count = [statearray count];
return count;
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
NSString *string;
if ([pickerType isEqualToString:#"picker"])
string = [array objectAtIndex:row];
if ([pickerType isEqualToString:#"statepicker"])
string = [statearray objectAtIndex:row];
return string;
}
// Set the width of the component inside the picker
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component {
return 300;
}
// Item picked
- (void)pickerView:(UIPickerView *)thePickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
select = YES;
if ([pickerType isEqualToString:#"picker"])
{
Txt.text = [array objectAtIndex:row];
}
if ([pickerType isEqualToString:#"statepicker"])
{
stateTxt.text = [statearray objectAtIndex:row];
}
}
- (void)pickerDone:(id)sender
{
if(select == NO)
{
if ([pickerType isEqualToString:#"picker"])
{
Txt.text = [array objectAtIndex:0];
}
else if ([pickerType isEqualToString:#"statepicker"])
{
stateTxt.text = [statearray objectAtIndex:0];
}
}
[actionSheet dismissWithClickedButtonIndex:0 animated:YES];
[actionSheet release];
actionSheet = nil;
}
}

UIPickers are OK to use, but in this particular case, where the list of entries can be a very long list and also the entries can some times may be more than a simple string, for example, if the country name is "Republic of Zimbabwe, Africa" or some thing like that UIPicker controllers cannot display the data in the best possible way. You can use table views and present them modally. Tableviews give you a much better way to do a selection if the list of entries are more than a hundred or so.

Related

UIPickerView 2nd component populates blank the second time the picker view is shown

I have a UIPickerView with 2 components. Selecting 1st components populates 2nd component. Looks like this:
Test Case:
Select any option in Component 0 and then pick any episode in Component 1 of picker and click Fitler which hides the picker.
Show the Picker again to select something else. The first component loads properly. The second component is blank like this screenshot:
Here's the code:
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view{
UILabel* tView = (UILabel*)view;
if (!tView){
tView = [[UILabel alloc] init];
tView.textAlignment = NSTextAlignmentCenter;
// Setup label properties - frame, font, colors etc
//...
//adjustsFontSizeToFitWidth property to YES
if(pickerView == self.seasonEpiPickerView && component == 1){
tView.font= [UIFont systemFontOfSize:12];
tView.adjustsFontSizeToFitWidth = YES;
}
}
// Fill the label text here
if (pickerView == self.seasonEpiPickerView)
{
if (component == 0) {
if (row == 0) {
item = #"All";
} else {
//NSLog(#"c1:%ld", (long)row);
item = [NSString stringWithFormat:#"S%#", ((Season *)[self.media.seasonManager.seasonArray objectAtIndex:row-1]).seasonNr];
}
} else if (component == 1){
if(self.media.seasonManager && self.media.seasonManager.seasonArray && [self.media.seasonManager.seasonArray count]>0 ) {
Season* tempSeason = self.media.seasonManager.seasonArray[[self.seasonEpiPickerView selectedRowInComponent:0]-1];
item = [NSString stringWithFormat:#"%#.%# \"%#\"", tempSeason.seasonNr, [NSString stringWithFormat: #"%02d", [((Episode *)[tempSeason.episodeManager.episodeArray objectAtIndex:row]).episodeNr intValue]], ((Episode *)[tempSeason.episodeManager.episodeArray objectAtIndex:row]).title];
NSLog(#"c2:%ld:%#", (long)row, item);
}
}
}
tView.text = item;
return tView;
}
Edit:
Here's how I create the Picker in viewDidLoad
self.seasonPickerViewTextField = [[UITextField alloc] initWithFrame:CGRectZero];
[self.view addSubview:self.seasonPickerViewTextField];
self.seasonEpiPickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
self.seasonEpiPickerView.showsSelectionIndicator = YES;
self.seasonEpiPickerView.dataSource = self;
self.seasonEpiPickerView.delegate = self;
//add the toolbar for the season picker
UIToolbar *toolBar= [[UIToolbar alloc] initWithFrame:CGRectMake(0,0,screenWidth,44)];
[toolBar setBarStyle:UIBarStyleBlack];
UIBarButtonItem *barButtonDone = [[UIBarButtonItem alloc] initWithTitle:#"Filter " style:UIBarButtonItemStylePlain target:self action:#selector(filterByEpisode:)];
UIBarButtonItem *flexible = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
UIBarButtonItem *barCancelButton = [[UIBarButtonItem alloc] initWithTitle:#" Cancel" style:UIBarButtonItemStylePlain target:self action:#selector(cancelPicker:)];
toolBar.items = [NSArray arrayWithObjects: barCancelButton, flexible, barButtonDone, nil];
self.seasonPickerViewTextField.inputAccessoryView = toolBar;
// set change the inputView (default is keyboard) to UIPickerView
self.seasonPickerViewTextField.inputView = self.seasonEpiPickerView;
EDIT 2
doing a delayed reload when the picker view is presented the second time reloads the second component correctly. This seems very hawkish.
- (IBAction)pickEpisodeButton:(id)sender
{
[self.seasonPickerViewTextField becomeFirstResponder];
/* None of the following commented lines of code have any effect*/
//[self.seasonEpiPickerView selectRow:1 inComponent:0 animated:NO];
//[self.seasonEpiPickerView selectRow:selectedSeason inComponent:0 animated:YES];
//[self.seasonEpiPickerView selectRow:selectedEpisode inComponent:1 animated:YES];
//[self.seasonEpiPickerView reloadComponent:1];
//set a 1.5 sec timer to go to the next screen
[NSTimer scheduledTimerWithTimeInterval:0.1f target:self selector:#selector(loadSecondComponent) userInfo:nil repeats:NO];
}
-(void)loadSecondComponent {
[self.seasonEpiPickerView reloadComponent:1];
}

How can i display the Blood group in UITextField if user clicks the UIPickerview

Wish you happy new year to all iOS developers.I want to display Blood group in UITextfield.
So I should took UIPickerview and append the Blood group list.My requirement is if user hit the UITextfiled the UIPickerview will be displayed and user select the blood group and it will reflect the blood group item in UITextfield.I am trying to do this functionality. But I have got some problem to display blood group value in UITextfield.The problem is for example if I click the A-ve blood group this will be displayed as it is in UITextfield.But if i click the A+ve group it will display like A ve instead of A+ve in UITextfield. This is my problem.Any body please help me. Thanks in advance.
The given below is my code.
//Bloodgroupviewcontroller.m
arrChooseServices=[[NSMutableArray alloc]initWithObjects:#"A+ve",#"A-ve",#"B+ve",#"B-ve",#"AB+ve",#"AB-ve",#"O+ve",#"O-ve", nil];
bloodGroup=[[UITextField alloc]initWithFrame:CGRectMake(150, 200, 120, 20)];
bloodGroup.borderStyle=UITextBorderStyleRoundedRect;
bloodGroup.backgroundColor=[UIColor clearColor];
bloodGroup.backgroundColor=[UIColor colorWithRed:0.662745 green:0.662745 blue:0.662745 alpha:0.5];
[bloodGroup setUserInteractionEnabled:NO];
bloodGroup.font=[UIFont systemFontOfSize:14.0];
bloodGroup.contentVerticalAlignment=UIControlContentVerticalAlignmentCenter;
bloodGroup.textAlignment=NSTextAlignmentCenter;
bloodGroup.delegate=self;
bloodGroup.inputView=self.chooseServicePicker;
bloodGroup.inputAccessoryView=self.accessoryView;
[self.view addSubview:bloodGroup];
-(UIPickerView *)chooseServicePicker
{
if(chooseServicePicker==nil)
{
chooseServicePicker=[[UIPickerView alloc]init];
chooseServicePicker.delegate=self;
chooseServicePicker.dataSource=self;
chooseServicePicker.showsSelectionIndicator=YES;
}
return chooseServicePicker;
}
-(UIToolbar *)accessoryView
{
if ( accessoryView == nil )
{
accessoryView = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 30)];
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(onBloodGroupSelection)];
UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:#selector(cancel)];
accessoryView.items=[NSArray arrayWithObjects:doneButton,cancelButton, nil];
}
return accessoryView;
}
- (void)onBloodGroupSelection
{
NSInteger row = [self.chooseServicePicker selectedRowInComponent:0];
bloodGroup.text=[arrChooseServices objectAtIndex:row];
[bloodGroup resignFirstResponder];
}
About the + not displaying, I tested your code and it is working fine for me. I had to change the [bloodGroup setUserInteractionEnabled:NO]; to [bloodGroup setUserInteractionEnabled:YES]; to make the UITextField clickable. Still, try adding
- (void)pickerView:(UIPickerView *)pickerView didSelectRow: (NSInteger)row inComponent:(NSInteger)component{
bloodGroup.text = [arrChooseServices objectAtIndex:row] ;
}
to your code to make the UITextField change text when the UIPickerView is tapped.
Try this,
Add this method and other delegate method to ur class
- (void)pickerView:(UIPickerView *)pickerView didSelectRow: (NSInteger)row inComponent:(NSInteger)component
{
yourtextfield.text = [yourdataarray objectAtIndex:row] ;
}
Take a string globally as "selectedString"
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
selectedString = yourdataarray[row];
}
-(void)onBloodGroupSelection
{
bloodGroup.text= selectedString;
[self.view endEditing:YES];
}

Custom UIPickerView crash in iOS 7

I had made a Custom UIPickerView with three Components each showing label on Selection Indicator which is working fine in iOS 6.
But I am getting a crash in iOS 7.
Here is my code:
ViewController.h
#define kDaysComponent 0
#define kHoursComponent 1
#define kMinutesComponent 2
#import <UIKit/UIKit.h>
#import "LabeledPickerView.h"
#interface ViewController : UIViewController<UIPickerViewDataSource,UIPickerViewDelegate,UITextFieldDelegate>
{
NSMutableArray *arrDays;
NSMutableArray *arrHours;
NSMutableArray *arrMinutes;
LabeledPickerView *timePicker;
IBOutlet UITextField *txtTimeLimit;
}
#property(nonatomic, retain) NSMutableArray *arrDays;
#property(nonatomic, retain) NSMutableArray *arrHours;
#property(nonatomic, retain) NSMutableArray *arrMinutes;
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize arrDays;
#synthesize arrHours;
#synthesize arrMinutes;
- (void)viewDidLoad
{
self.arrDays = [[NSMutableArray alloc]initWithCapacity:100];
for (NSInteger i = 0; i < 100; i++){
[arrDays addObject:[NSString stringWithFormat:#"%d",i]];
}
//self.arrDays = arrDays;
self.arrHours = [[NSMutableArray alloc]initWithCapacity:24];
for (NSInteger i = 0; i < 24; i++){
[arrHours addObject:[NSString stringWithFormat:#"%d",i]];
}
//self.arrHours = arrHours;
self.arrMinutes = [[NSMutableArray alloc]initWithCapacity:60];
for (NSInteger i = 0; i < 60; i++){
[arrMinutes addObject:[NSString stringWithFormat:#"%d",i]];
}
//self.arrMinutes = arrMinutes;
[self.navigationController setNavigationBarHidden:YES];
[super viewDidLoad];
}
-(IBAction)Click:(id)sender{
timePicker = [[LabeledPickerView alloc] init];
timePicker.showsSelectionIndicator = YES;
timePicker.dataSource = self;
timePicker.delegate = self;
[timePicker addLabel:#"Days" forComponent:kDaysComponent forLongestString:#"Hours"];
[timePicker addLabel:#"Hours" forComponent:kHoursComponent forLongestString:#"Hours"];
[timePicker addLabel:#"Mins" forComponent:kMinutesComponent forLongestString:#"Mins"];
UIToolbar* toolbar = [[UIToolbar alloc] init];
toolbar.barStyle = UIBarStyleBlackTranslucent;
[toolbar sizeToFit];
//to make the done button aligned to the right
UIBarButtonItem *flexibleSpaceLeft = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *flexibleSpaceRight = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem* doneButton = [[UIBarButtonItem alloc] initWithTitle:#"Done" style:UIBarButtonItemStyleDone target:self action:#selector(doneClicked:)];
UIBarButtonItem *unlimitedButton = [[UIBarButtonItem alloc] initWithTitle:#"Unlimited" style:UIBarButtonItemStyleBordered target:self action:#selector(unlimitedClicked:)];
[unlimitedButton setTintColor:[UIColor colorWithRed:100.0f/255.0f green:197.0f/255.0f blue:84.0f/255.0f alpha:1.0f]];
UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithTitle:#"Cancel" style:UIBarButtonItemStyleDone target:self action:#selector(cancelClicked:)];
[toolbar setItems:[NSArray arrayWithObjects:cancelButton,flexibleSpaceLeft,unlimitedButton,flexibleSpaceRight,doneButton, nil]];
//custom input view
txtTimeLimit.inputView = timePicker;
txtTimeLimit.inputAccessoryView = toolbar;
}
-(void)doneClicked:(id) sender
{
[txtTimeLimit resignFirstResponder]; //hides the pickerView
NSInteger daysRow = [timePicker selectedRowInComponent: kDaysComponent];
NSInteger hoursRow = [timePicker selectedRowInComponent: kHoursComponent];
NSInteger minutesRow = [timePicker selectedRowInComponent: kMinutesComponent];
NSString *days = [arrDays objectAtIndex:daysRow];
NSString *hours = [arrHours objectAtIndex:hoursRow];
NSString *minutes = [arrMinutes objectAtIndex:minutesRow];
txtTimeLimit.text = [[NSString alloc] initWithFormat:
#"Expires in [%#] Days [%#] Hours [%#] Minutes.",days,hours,minutes];
if ([txtTimeLimit.text isEqualToString:#""])
{
}
else
{
}
}
-(void)cancelClicked:(id) sender
{
[txtTimeLimit resignFirstResponder]; //hides the pickerView
}
-(void)unlimitedClicked:(id) sender
{
[txtTimeLimit resignFirstResponder]; //hides the pickerView
txtTimeLimit.text = #"Select Time Limit";
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark Picker View Delegate
- (NSInteger)numberOfComponentsInPickerView:(LabeledPickerView *)pickerView
{
return 3;
}
- (NSInteger)pickerView:(LabeledPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
if (component == kDaysComponent)
{
return [self.arrDays count];
}
else if (component == kHoursComponent)
{
return [self.arrHours count];
}
else if (component == kMinutesComponent)
{
return [self.arrMinutes count];
}
return 0;
}
- (NSString *)pickerView:(LabeledPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
if (component == kDaysComponent)
{
NSLog(#"%#",[arrDays objectAtIndex:row]);
return [self.arrDays objectAtIndex:row];
}
else if (component == kHoursComponent)
{
NSLog(#"%#",[arrHours objectAtIndex:row]);
return [self.arrHours objectAtIndex:row];
}
else if (component == kMinutesComponent)
{
return [self.arrMinutes objectAtIndex:row];
}
return 0;
}
#pragma mark TEXT FIELD DELEGATE
- (BOOL)textFieldShouldBeginEditing:(UITextField *)aTextField
{
[self Click:aTextField];
return YES;
}
I am showing UIPickerView as an input view for UITextField and each time I am getting this error in iOS 7 only:
Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 5 beyond bounds [0 .. 2]'
I don't know what's wrong with it. Can anyone please help me on this?
Your crash is telling you what the problem is:
-[__NSArrayM objectAtIndex:]: index 5 beyond bounds [0 .. 2]'
You are trying to get a value of object at the index 5 when your array only contains 3 objects.
Put a break point in and check the arrays contain what you expect and the component value is what you expect.
Please try to set txtTimeLimit.inputView after delays like one second.
[self performSelector:#selector(setInputView:) withObject:timePicker afterDelay:1];
- (void)setInputView:(LabeledPickerView*)picker {
txtTimeLimit.inputView = picker;
}
I think it's something doing with the animation....
You have to concern in few things,
First is the delegate and datasource method.
If u get the warning on delegate and datasource then correct the code like this
timePicker.dataSource = (id)self;
timePicker.delegate = (id)self;
Then Check the array. Hopefully it will solve your problem.

Popup UIPickerView

I know lots of people have asked same question, and I've tried lots of them, I don't know what part that I miss, I still can get it to work.
I have a 9*9 table that I want to display and change, because of the size of Iphone Screen, I'm thinking to show one column a time.
What I want is to press the top left button and a UIPickerView will popup allows me to choose which column to display, then reload the UITextFields.
Can anyone give me a detailed answer? I'm still relatively new in this(couple months).
Thank you in advance.
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil
delegate:nil
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:nil];
[actionSheet setActionSheetStyle:UIActionSheetStyleBlackTranslucent];
CGRect pickerFrame = CGRectMake(0, 40, 0, 0);
UIPickerView *pickerView = [[UIPickerView alloc] initWithFrame:pickerFrame];
pickerView.showsSelectionIndicator = YES;
pickerView.dataSource = self;
pickerView.delegate = self;
[actionSheet addSubview:pickerView];
UISegmentedControl *closeButton = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObject:#"Close"]];
closeButton.momentary = YES;
closeButton.frame = CGRectMake(260, 7.0f, 50.0f, 30.0f);
closeButton.segmentedControlStyle = UISegmentedControlStyleBar;
closeButton.tintColor = [UIColor blackColor];
[closeButton addTarget:self action:#selector(dismissActionSheet:) forControlEvents:UIControlEventValueChanged];
[actionSheet addSubview:closeButton];
[closeButton release];
[actionSheet showInView:[[UIApplication sharedApplication] keyWindow]];
[actionSheet setBounds:CGRectMake(0, 0, 320, 485)];
Above is the code I found, it pops up alright, I have problem adding array to pickerview, and can anyone tell me how should dismissActionSheet method be?
Thank you.
Ok, so I think I understand what you are asking, correct me if this isn't what you need help with...but to add an array (of presumably NSStrings) to the picker view you need to use the - (NSString *)pickerView:titleForRow:forComponent: delegate method. Here is a quick examle:
//Say you have an array of strings you want to present in the pickerview like this
NSArray *arrayOfStrings = [NSArray arrayWithObjects:#"One", #"Two", #"Three", #"Four", nil];
//First we need to say how many rows there will be in the pickerview
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return [arrayOfStrings count];
}
//Do the same for components (columns) in pickerview
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 1;
}
//Here we set the actual title/string on the pickerview
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{
if(component==0){
//Grab the nth string from array
return [arrayOfStrings objectAtIndex:row];
}
}
//This is called if a user taps a row
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
if(component==0)
NSLog(#"The User Selected the row titled %#", [arrayOfStrings objectAtIndex:row]);
}
Similairly with actionsheet, you need to add the delegate method for handling when a user clicks a button on the actionsheet
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{
if(buttonIndex==0){
NSLog(#"First Button Clicked");
} else if( buttonIndex == 1){
NSLog(#"Second Button Clicked");
}
}

How to Show UIPickerView when selecting UITextField

Here is a screenshot of what I did till now:
So what I am trying to do is when you select "pick a name" Textfield I need a Picker to show up, with the input #"Jack".
Since iOS 3.2, UITextField supports the inputView property to assign a custom view to be used as a keyboard, which provides a way to display a UIPickerView:
You could use the inputView property of the UITextField, probably combined with the inputAccessoryView property. You assign your pickerView to the inputView property, and, to dismiss the picker, a done button to the inputAccessoryView property.
UIPickerView *myPickerView = [[UIPickerView alloc] init];
//myPickerView configuration here...
myTextField.inputView = myPickerView;
Like that. This will not give you a direct way to dismiss the view since your UIPickerView has no return button, which is why I recommend to use the inputAccessoryView property to display a toolbar with a done button (the bar is just for aesthetics, you might as well just use a UIButton object):
UIToolbar *myToolbar = [[UIToolbar alloc] initWithFrame:
CGRectMake(0,0, 320, 44)]; //should code with variables to support view resizing
UIBarButtonItem *doneButton =
[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
target:self action:#selector(inputAccessoryViewDidFinish)];
//using default text field delegate method here, here you could call
//myTextField.resignFirstResponder to dismiss the views
[myToolbar setItems:[NSArray arrayWithObject: doneButton] animated:NO];
myTextField.inputAccessoryView = myToolbar;
I use this and find this a lot cleaner than adding a subview and animating the UIPicker
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
responder = textField;
if ([textField isEqual:self.txtBirthday]) {
UIDatePicker *datepicker = [[UIDatePicker alloc] initWithFrame:CGRectZero];
[datepicker setDatePickerMode:UIDatePickerModeDate];
textField.inputView = datepicker;
}
return YES;
}
it will work for you .. i have edited it .and for that you have to set delegate for textfield. and create a UIPIckrView in NIb file.
- (BOOL) textFieldShouldBeginEditing:(UITextView *)textView
{
pickrView.frame = CGRectMake(0, 500, pickrView.frame.size.width, pickrView.frame.size.height);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:.50];
[UIView setAnimationDelegate:self];
pickrView.frame = CGRectMake(0, 200, pickrView.frame.size.width, pickrView.frame.size.height);
[self.view addSubview:pickrView];
[UIView commitAnimations];
return NO;
}
Well, you could rely on the UITextFieldDelegate to handle this kind of functionality.
Inside the
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
is where you would set the text of your current UITextField as well as initializing and showing the UIPickerView.
Important notice:
You might also want to conform to the UIPickerViewDelegate.
HTH
Swift:
internal var textFieldHandlerToolBar: UIToolbar = {
let tb = UIToolbar.init(frame: CGRect.init(origin: .zero, size: CGSize.init(width: UIScreen.main.bounds.width, height: 44.0)))
let doneBarButton = UIBarButtonItem.init(title: "Done", style: UIBarButtonItemStyle.done, target: self, action: #selector(actionDonePickerSelection))
tb.setItems([doneBarButton], animated: false)
return tb
}()
internal var pickerView: UIPickerView = {
let pv = UIPickerView.init()
return pv
}()
#objc internal func actionDonePickerSelection() {
textField.resignFirstResponder()
}
override func viewDidLoad() {
super.viewDidLoad()
self.pickerView.delegate = self
self.pickerView.datasource = self
}
Use it like this:
textField.inputAccessoryView = self.textFieldHandlerToolBar
textField.inputView = self.pickerView
What you can do is, create a UIButton with custom type on UITextField. Both having equal sizes. On the touch of button you can show UIPickerView.
http://tmblr.co/ZjkSZteCOUBS
I have the code and everything laid out in my blog to do this exactly. But below, I have the basic concept laid out.
Basically the solution involves an opensource project called ActionSheetPicker on github, and implementing the function textFieldShouldBeginEditing on the UITextFieldDelegate. You can dismiss the keyboard there and provide a UIPickerView instead. The basic code is listed here:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
// We are now showing the UIPickerViewer instead
// Close the keypad if it is showing
[self.superview endEditing:YES];
// Function to show the picker view
[self showPickerViewer :array :pickerTitle];
// Return no so that no cursor is shown in the text box
return NO;
}
ViewController.h
#interface ChangeCurrencyVC : UIViewController <UIPickerViewDataSource, UIPickerViewDelegate>
{
NSArray *availableCurreniesArray;
}
#property (weak, nonatomic) IBOutlet UITextField *chooseCurrencyTxtFldRef;
ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
availableCurreniesArray = #[#"Indian Rupee", #"US Dollar", #"European Union Euro", #"Canadian Dollar", #"Australian Dollar", #"Singapore Dollar", #"British Pound", #"Japanese Yen"];
// Do any additional setup after loading the view.
[self pickerview:self];
}
#pragma mark - picker view Custom Method
-(void)pickerview:(id)sender{
UIPickerView *pickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
pickerView.showsSelectionIndicator = YES;
pickerView.dataSource = self;
pickerView.delegate = self;
// set change the inputView (default is keyboard) to UIPickerView
self.chooseCurrencyTxtFldRef.inputView = pickerView;
// add a toolbar with Cancel & Done button
UIToolbar *toolBar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
toolBar.barStyle = UIBarStyleBlackOpaque;
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(doneTouched:)];
UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:#selector(cancelTouched:)];
// the middle button is to make the Done button align to right
[toolBar setItems:[NSArray arrayWithObjects:cancelButton, [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil], doneButton, nil]];
self.chooseCurrencyTxtFldRef.inputAccessoryView = toolBar;
}
#pragma mark - doneTouched
- (void)cancelTouched:(UIBarButtonItem *)sender{
// hide the picker view
[self.chooseCurrencyTxtFldRef resignFirstResponder];
}
#pragma mark - doneTouched
- (void)doneTouched:(UIBarButtonItem *)sender{
// hide the picker view
[self.chooseCurrencyTxtFldRef resignFirstResponder];
// perform some action
}
#pragma mark - The Picker Challenge
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 1;
}
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
return [availableCurreniesArray count];
}
- (nullable NSString *)pickerView:(UIPickerView *)pickerView titleForRow: (NSInteger)row forComponent:(NSInteger)component{
return availableCurreniesArray[row];
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
self.chooseCurrencyTxtFldRef.text = availableCurreniesArray[row];
}

Resources