pickerview for iphone that looks like country select feature - iphone

I want to create a picker that looks and works like the country select field of itune store account.
Here is what I am talking about.
http://i38.tinypic.com/5p0w91.jpg
This picker doesn't have a row highlighted. It has "correct" sign marked in front of selected row. user can scroll this picker and then select the row so "correct" sign will appear in front of newly selected row.
Can someone please help?

This can be accomplished relatively easily using a picker with custom component views. Use an instance variable to keep track of your selected row, and change the color of your label accordingly. If you wanted to include the check mark, you'd need to go a step further and use a custom subclass of UIView rather than a simple UILabel.
#interface ViewContainingPicker
{
NSUInteger mySelectedRow;
}
#end
#implementation ViewContainingPicker
// Init, Picker setup, etc
- (UIPickerView *)myPickerView
{
// Create picker, set mySelectedRow to NSNotFound
mySelectedRow = NSNotFound;
return myPickerView;
}
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
UILabel *label = (UILabel *)view;
if (nil == label) {
UILabel *label = [[[UILabel alloc] initWithFrame:CGRectMake(0, 0, PICKER_WIDTH, PICKER_ROW_HEIGHT)] autorelease];
}
label.text = #"Label for this row";
// Selected Row will be blue
if (row == mySelectedRow) {
label.textColor = [UIColor blueColor];
} else {
label.textColor = [UIColor blackColor];
}
return label;
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
// Just set selected component and reload, color will change in dataSource pickerView:viewForRow:forComponent:reusingView:
mySelectedRow = row;
[pickerView reloadComponent:component];
}

I'm not familiar with coding apps, but for a browser-based UI (Safari), you would just use a simple drop-down menu:
<select>
<option>Country 1</option>
<option>Country 2</option>
...
<option>Country N</option>
</select>
Guessing whatever is the equivalent in the iPhone SDK should work the same.

Related

UIPickerview Multiple TextFields Xcode

I'm looking for a way to use a single UIPickerview for two different textfields. I'd like to have the pickerview popup when each textfield is selected. After the user selects their item, the item will populate the specific text field. The picker would have to populate based on the textfield chosen.
I've read this:
How to use one UIPickerView for multiple textfields in one view?
and this:
How to use UIPickerView to populate different textfields in one view?
and this:
Multiple sources for UIPickerView on textfield editing
However, none gives a complete solution.
I'm very new at Xcode so I'd like a solution that includes steps to set the storyboard also.
I appreciate any help as i've researched this for weeks.
EDIT: HERE IS MY CODE:
.h:
#import <UIKit/UIKit.h>
#interface klViewController : UIViewController <UIPickerViewDelegate, UIPickerViewDataSource> {
IBOutlet UITextField *textField1;
IBOutlet UITextField *textField2;
NSMutableArray *pickerArray1;
NSMutableArray *pickerArray2;
UIPickerView *pickerView;
}
#property(nonatomic,retain) IBOutlet UITextField *textField1;
#property(nonatomic,retain) IBOutlet UITextField *textField2;
#property(nonatomic,retain) IBOutlet UIPickerView *pickerView;
#end
.m:
#import "klViewController.h"
#interface klViewController ()
#end
#implementation klViewController
#synthesize pickerView;
#synthesize textField1;
#synthesize textField2;
int variabla;
-(void)textFieldDidBeginEditing:(UITextField *)textField{
[pickerView setHidden:YES];
if (textField1.editing == YES) {
[textField1 resignFirstResponder];
[pickerView setHidden:NO];
variabla = 1;
}else if (textField2.editing == YES) {
[textField2 resignFirstResponder];
[pickerView setHidden:NO];
variabla = 2;
}
NSLog(#"variabla %d",variabla);
[pickerView reloadAllComponents];
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView;
{
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component;
{
if (variabla == 1) {
return [pickerArray1 count];
}else if (variabla == 2) {
return [pickerArray2 count];
}else {
return 0;
}
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component;
{
if (variabla == 1) {
return [pickerArray1 objectAtIndex:row];
}else if (variabla == 2) {
return [pickerArray2 objectAtIndex:row];
}else {
return 0;
}
}
- (void)textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
}
- (void)viewDidLoad {
[super viewDidLoad];
[pickerView setHidden:YES];
pickerArray1 = [[NSMutableArray alloc] initWithObjects:#"0", #"1", #"2", nil];
pickerArray2 = [[NSMutableArray alloc] initWithObjects:#"3", #"4", #"5", nil];
}
#end
HERE IS A SCREEN SHOT OF MY STORYBOARD:
STATUS UPDATE:
When I run the program:
1) the pickerview is hidden.
2) when I select a textfield, the picker view appears and populates correctly depending on the textfield selected.
PROBLEMS:
1) Picker doesn't go away when click outside of the textfield.
2) Textfields don't populated when a row in the Picker is selected.
Hope this provides more insight.
1) Picker doesn't go away when click outside of the textfield.
You have no code that attempts to make the picker go away when that happens. Try adding a simple tap gesture recognizer to the view. Add a line to viewDidLoad like:
[self.view addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(backgroundTap:)]];
Then implement the function simply like:
-(void)backgroundTap:(UITapGestureRecognizer *)tapGR{
self.pickerView.hidden = YES;
// And maybe..
variabla = 0;
}
Since you are making the picker appear and disappear using the hidden property this will work very simply. There are other more sophisticated ways to do this which I hope you explore. Generally the picker is set as the textfield's inputView property; that is worth investigating.
2) Textfields don't populated when a row in the Picker is selected.
You haven't handled the picker's pickerView:didSelectRow:inComponent: delegate method. That's the method that gets called when the picker stops turning and lands on an item. Don't assume that this is the item the user selected it will be called multiple times.
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
NSString *text = [self pickerView:pickerView titleForRow:row forComponent:component];
UITextField *current = nil;
if (variabla == 1) current = self.textField1;
else if (variabla == 2) current = self.textField2;
current.text = text;
}
That should get your implementation working. One more thing though variabla is an instance variable and should be declared in curly braces immediately following the #interface or #implementation line.
#implementation klViewController {
int variabla;
}
#synt....
Give the Tag of two Different textfield for identify which textfield you select and everything is ok you just need to change below method.
Hope This Work
-(void)textFieldDidBeginEditing:(UITextField *)textField {
if ([textField viewWithTag:100]) {
[textField resignFirstResponder];
[self.View1 setHidden:NO];
variable=1;
}
else if ([textField viewWithTag:101]) {
[textField resignFirstResponder];
[self.View1 setHidden:NO];
variable=2;
}
[_Picker_view reloadAllComponents];
}
Thanks :)
Make sure you have declared the Picker View object in the header file.
In the header file, import the UITextFieldDelegate protocol:
#interface MyView:UIViewController < UITextFieldDelegate>
In IB, set a tag for each text field you have.
In the *.m file, implement the textFieldShouldBeginEditing method, update the PickerView array Data Source and Reload all the picker view components.
-(BOOL) textFieldShouldBeginEditing:(UITextField *)textField {
if (textField.tag == 1) {
itemsArray = [[NSArray alloc] arrayWithObjects:#"A", #"B"];
}
if (textField.tag == 2) {
itemsArray = [[NSArray alloc] arrayWithObjects:#"Green", #"Yellow"];
}
[myPickerView reloadAllComponents];
}
Make sure you import the UIPickerViewDelegate and UIPickerViewDataSource in the header file.
You can use the same picker view for as many text fields as you want, to change the content of the picker view according to the selected text field you need to replace the data source of the picker view with different items whenever a text field is being selected and then reload the picker view components.
Well my friend, I'm afraid it's a little bit to complicated to explain here.
You can set object's tag value in the IB properties menu.
Once you dragged a PickerView into your view and it's selected, you can change the tag attribute in the Object Properties menu (on the side).
I think you should look for tutorials that will show you how to setup a simple picker view, or table view (they work very similar to one another) and that will give you much more information on how to do what you want to do. In a nutshell, every Picker View takes information from a Data Source, you can create an array that contains some strings and have the picker view load each item in the array as a row. I have a small website with some beginners information, check it out.
http://i-tutor.weebly.com/index.html
In .h
#interface TQViewController : UIViewController<UIPickerViewDelegate>
{
UITextField *textfield;
UIPickerView *Picker1;
NSArray *Array1,*Array2;
}
end
and in .m
- (void)viewDidLoad
{
[super viewDidLoad];
//TextField
textfield=[[UITextField alloc]initWithFrame:CGRectMake(5,5,310,40)];
textfield.borderStyle = UITextBorderStyleRoundedRect;
textfield.backgroundColor=[UIColor whiteColor];
textfield.textAlignment = UITextAlignmentCenter;
textfield.placeholder = #"<enter amount>";
[self.view addSubview:textfield];
textfield1=[[UITextField alloc]initWithFrame:CGRectMake(5,100,310,40)];
textfield1.borderStyle = UITextBorderStyleRoundedRect;
textfield1.backgroundColor=[UIColor whiteColor];
textfield1.textAlignment = UITextAlignmentCenter;
textfield1.placeholder = #"<enter amount>";
[self.view addSubview:textfield1];
// PickerView1
Array1=[[NSArray alloc]initWithObjects:#"USD",#"INR",#"EUR", nil];
Picker1=[[UIPickerView alloc]initWithFrame:CGRectMake(0, 50, 320,10)];
Picker1.delegate=self;
Picker1.tag=PICKER1_TAG;
Picker1.showsSelectionIndicator=YES;
[self.view addSubview:Picker1];
Array2=[[NSArray alloc]initWithObjects:#"USD",#"INR",#"EUR", nil];
}
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
if([textfield becomeFirstResponder])
return [Array1 count];
if([textfield1 becomeFirstResponder])
return [Array2 count];
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
NSString *title;
if([textfield becomeFirstResponder])
{
title=[Array1 objectAtIndex:row];
return title;
}
([textfield1 becomeFirstResponder])
{
title=[Array2 objectAtIndex:row];
return title;
}
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
if([textfield becomeFirstResponder])
{
//your code
}
([textfield1 becomeFirstResponder])
{
//your code
}
}

Custom UIPickerView

I want to use custom picker view that will add a check sign in front of selected row.
I have used apple sample code for custom UIPickerView on the UICatalog example. I was able to add the check sign for a given row when creating the picker. But I failed to add it when the user rotate the wheel to select new row and also to remove it from the previously added row. Any help would be appreciated.
Thanks,
1) Create subclass of UIView that will represent row in picker. Define property, for example, isChecked, which will show/hide checkmark on this view
2) In the – pickerView:didSelectRow:inComponent: call – viewForRow:forComponent: for previously selected row, set isChecked=NO
3) call – viewForRow:forComponent: for currently selected row and set isChecked=YES;
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
MyCustomRowView *prevRowView = [pickerView viewForRow:currentlySelectedRow forComponent:component];
prevRowView.isChecked = NO;
MyCustomRowView *currentRowView = [pickerView viewForRow:row forComponent:component];
currentRowView.isChecked = YES;
//then save currently selected row
currentlySelectedRow = row;
}
4) you also should check currently selected row when you is requested for it:
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
....
//Create or reuse view
....
rowView.isChecked = (row == currentlySelectedRow);
}
As you are not providing any code, all we can give you is a general advise;
make sure the viewController showing your UIPickerView instance is inheritating the UIPickerViewDelegate-protocol
set the delegate of your UIPickerView towards this viewController; e.g. pickerView.delegate = self;
implement - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
within the above implementation, remove any checkmark previously added and add a new one to the row selected.

Custom UITableViewCell redraw issues

I have a custom UITableView cell that I've added a textbox to for editing, that shows and hides based on the edit mode. I've also tried adding a vertical line that shows when editing, and it does that, but I'm running into some drawing issues. I just added a green checkmark rightView to start working on input validation feedback, and I'm seeing similar issues.
Here is the code for the cell, and part of my cellForRowAtIndexPath.
#import <UIKit/UIKit.h>
#interface EditableCellStyle2 : UITableViewCell {
CGRect editRect;
UITextField *editField;
UIView *lineView;
}
#property (nonatomic, readonly, retain) UITextField *editField;
#property (nonatomic, readonly, retain) UIView *lineView;
#end
#import "EditableCellStyle2.h"
#implementation EditableCellStyle2
#synthesize editField;
#synthesize lineView;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code.
editRect = CGRectMake(83, 12, self.contentView.bounds.size.width-83, 19);
editField = [[UITextField alloc] initWithFrame:editRect];
editField.font = [UIFont boldSystemFontOfSize:15];
editField.textAlignment = UITextAlignmentLeft;
editField.textColor = [UIColor blackColor];
editField.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight;
[self.contentView addSubview:editField];
self.editField.enabled = NO;
self.editField.hidden = YES;
lineView = [[UIView alloc] initWithFrame:CGRectMake(80, 0, 1, self.contentView.bounds.size.height)];
self.lineView.backgroundColor = [UIColor lightGrayColor];
[self.contentView addSubview:lineView];
self.lineView.hidden = YES;
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state.
}
-(void)layoutSubviews
{
[super layoutSubviews]; // layouts the cell as UITableViewCellStyleValue2 would normally look like
editRect = CGRectMake(83, 12, self.contentView.frame.size.width-self.detailTextLabel.frame.origin.x-10, 19);
editField.frame = editRect;
}
- (void)willTransitionToState:(UITableViewCellStateMask)state {
[super willTransitionToState:state];
if (state & UITableViewCellStateEditingMask) {
self.detailTextLabel.hidden = YES;
self.editField.enabled = YES;
self.lineView.hidden = NO;
self.editField.hidden = NO;
}
}
- (void)didTransitionToState:(UITableViewCellStateMask)state {
[super didTransitionToState:state];
if (!(state & UITableViewCellStateEditingMask)) {
self.editField.enabled = NO;
self.editField.hidden = YES;
self.lineView.hidden = YES;
self.detailTextLabel.hidden = NO;
self.editField.text = self.detailTextLabel.text;
}
}
- (void)dealloc {
[editField release];
[lineView release];
[super dealloc];
}
#end
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// handling every section by hand since this view is essentially static. Sections 0, 1, 2, and 4 use a generic editable cell.
// Section 3 uses the multiline address cell.
static NSString *CellIdentifier = #"Cell";
EditableCellStyle2 *cell = (EditableCellStyle2 *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (indexPath.section == 0 || indexPath.section == 1 || indexPath.section == 2 || indexPath.section == 4) {
if (cell == nil) {
cell = [[[EditableCellStyle2 alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:CellIdentifier] autorelease];
}
}
// Configure the Odometer
if (indexPath.section == 0) {
NSArray *array = [sectionsArray objectAtIndex:indexPath.section];
NSDictionary *dictionary = [array objectAtIndex:indexPath.row];
cell.textLabel.text = #"Odometer";
cell.detailTextLabel.text = [NSString stringWithFormat:#"%#", [dictionary objectForKey:#"Odometer"]];
cell.tag = kOdometer;
cell.editField.text = cell.detailTextLabel.text;
cell.editField.placeholder = #"Odometer";
cell.editField.tag = kOdometer;
cell.editField.keyboardType = UIKeyboardTypeNumberPad;
// Create a view for the green checkmark for odometer input validation and set it as the right view.
UIImage *checkImage = [UIImage imageNamed:#"tick.png"];
UIImageView *checkImageView = [[[UIImageView alloc] initWithImage:checkImage] autorelease];
cell.editField.rightView = checkImageView;
cell.editField.rightViewMode = UITextFieldViewModeAlways;
}
return cell;
}
There is more to it but all the cells are built the same way.
The problems are that, when in edit mode, the vertical lines will display properly. When I leave edit mode, any cells that were off screen when I go to normal mode still have the vertical line (it doesn't get hidden). Also, now that I've added the imageView for the checkmark indicator, any cells that are off screen when switching modes gain the checkmark. (only section 0 sets it up).
I've also noticed that if i do cell.setNeedsDisplay, the text label and detail text label won't update if the data source has been updated. I have to do [self.tableView reloadData] which skips any active animations.
I'm sure these issues are related to me using a custom cell + dequeueReusableCellWithIdentifier, but I can't find exactly what.
Any feedback or a push in the right direction would be appreciated.
Edit:
Not using reusable cells seems to have resolved the above issues. I'm still open to feedback on the cell code.
I forgot one other issue that may or may not be related. One of my cells has a "tap to view list" button. If I enter data into the cells while in edit mode, then hit that button to choose some info from a list (it displays a modal table view), when I dismiss the modal view, all of the cells' edited data has reverted to their original state. I'm not calling reload data when I dismiss the modal view controller. I thought this might be fixed by not using reusable cells but it isn't.
You need to prepare the cell for reuse. Try adding this to the EditableCellStyle2 implementation:
- (void)prepareForReuse {
[super prepareForReuse];
[self didTransitionToState:UITableViewCellStateDefaultMask];
}
Maybe you trimmed too much for your post, but in the posted code your reusable cell handling is all wrong.
First of all, each different type of cell needs its own CellIdentifier. In your case (judging from your code comment), that means at least a different identifier for section 3 versus sections 0, 1, 2, and 4. You may also want to do a separate identifier for section 0, so you don't have to keep removing and readding that checkmark. The different identifier needs to be used for both the dequeueReusableCellWithIdentifier: and initWithStyle:reuseIdentifier:` for the appropriate sections.
The second problem is that you are not resetting the cells correctly. There are two "kinds" of initialization that must be done to a UITableViewCell: initialization that is the same for every cell of its type, and initialization that depends on the specific row being displayed. The first kind can (and should) only be done once, when a new cell is allocated. The second kind must be done every time through tableView:cellForRowAtIndexPath:. You seem to be doing the first correctly for your EditableTableCell2 class in its init method, but I see nowhere in there where you do the per-row initialization: you never reset selected, or the cell state, or the contents of the edit field, or remove the checkImageView since you are using the same kind of cell for section 0 versus the other sections. If you want, the reset selected, state, and clearing out the checkbox image and field contents can be done in prepareForReuse on your EditableTableCell2 class.
The third problem, which is almost certainly due to over-trimming, is that you never create this "multiline address" cell for section 3. You'll end up maybe reusing a random EditableTableCell2, or maybe crashing on an exception from the framework when you return nil from tableView:cellForRowAtIndexPath:.

Cocoa-Touch: UIPickerView viewForRow is changing row orders

I have a UIPickerView. I'm customizing it's rows via it's delegate's viewForRow as follows:
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view {
if (view) {
return view;
} else {
NSString *s = [datePickerValues objectAtIndex:row];
UILabel *l = [[[UILabel alloc] initWithFrame:CGRectMake(0, 0, 300, 44)] autorelease];
// l.text = s;
l.text = [NSString stringWithFormat:#"%# r:%ld", s, row];
l.font = [UIFont boldSystemFontOfSize:18];
l.textAlignment = UITextAlignmentCenter;
l.backgroundColor = [UIColor purpleColor];
return l;
}
}
When I spin it around for a bit, the rows get mixed up.
I even get the same row two or more times, and sometimes missing rows. The row count is always at 10 tho, it just seems to be calling the delegate's viewForRow method with a wrong row parameter.
I'm using the row paremeter to identify the rows. (as the documentation says). It has a single component, so the component param is always 0, I've verified this with the debugger.
Another weird thing, according to the documentation, once I create the view for a specific row, the delegate's view parameter will have that view, but using the debugger I've seen that the delegate's viewForRow is sometimes called more than once for the same row with a view = nil.
Any idea why this strange behavior? I'm new to cocoa and Obj-C, am I doing something wrong?
EDIT:
From the docs:
view - A view object that was previously used for this row, but is now hidden and cached by the picker view.
So this means that the 2nd time the delegate's viewForRow is called for a specific row, it will have the view returned on call 1. This makes sense since this way the delegate wouldn't have to re-create the view over and over as the user spins the control.
I've verified that in fact the viewForRow is called EVERY time a row is displayed, even if it was previously displayed.
What then is the use for the view parameter? The two answers so far don't seem to be valid.
You must update the data in the view each time this method is called. By not updating you are returning stale/duplicated data.
Looks like the problem is that UIPickerView tries to reuse your already created views for new rows for performance reasons. In this case ( (view != nil) ) you just return the same view you had for some previous row.
If your view is always is a UILabel you can rewrite your code like that (sorry didn't compile it):
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view {
NSString *s = [datePickerValues objectAtIndex:row];
UILabel *l = (view != nil)? view : [[[UILabel alloc] initWithFrame:CGRectMake(0, 0, 300, 44)] autorelease];
l.text = [NSString stringWithFormat:#"%# r:%ld", s, row];
l.font = [UIFont boldSystemFontOfSize:18];
l.textAlignment = UITextAlignmentCenter;
l.backgroundColor = [UIColor purpleColor];
return l;
}
it must work ok.
I see this is a very old question, but I was having the same issue with iOS7 and could not find a satisfactory answer. When I tried to tap into the 'row' parameter from the viewForRow delegate method, it would return incorrect and mixed up values.
I was able to solve this issue by doing the following,
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view {
...
//Create a label
//Set a tag for label
//Add label to view as a subview
//return view
if (component == 1) {
view = [[UIView alloc] init];
view.backgroundColor = [UIColor clearColor];
correctRowLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 30, 20)];
[correctRowLabel setText:[NSString stringWithFormat:#"%li", row]];
[correctRowLabel setTag:100];
[view addSubview: correctRowLabel];
return view;
}
After the component is setup as desired, at the beginning of the viewForRow delegate method, implement the following to view the correct row values,
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view {
UILabel* correctRow = (UILabel*)[pickerView viewWithTag:100];
NSInteger correctRowValue = [correctRow.text integerValue];
NSLog(#"Correct row is: %li",correctRowValue);
UILabel* correctRowLabel = nil;
...
EDIT:
I wanted to add that the rowHeightForComponent must be set to default and the label must be reset at the top of viewForRow method. It isn't working perfectly but it is significantly better than before. If i learn of anything else I'll update this post.

UIPickerView added to uitableviewcontroller.view won't rotate

I have a UIPickerView as subview in a UITableViewController, which I want to slide up in place when a certain row is clicked. I have implemented the necessary dataSource and delegate methods, but the pickerview acts weirdly. It acts as if it were mechanically jammed, it cannot rotate properly, it just moves a little. If I try to spin it a few times I get this message in the debugger console:
SendDelegateMessage: delegate failed
to return after waiting 10 seconds.
main run loop mode:
UITrackingRunLoopMode If you were not
using the touch screen for this entire
interval (which can prolong this
wait), please file a bug.
I googled for this, to no avail.
Anyway, here is the relevant code. As you may guess, this is a number picker (to choose a percentage value).
- (void)viewDidLoad {
[super viewDidLoad];
percentPicker = [[UIPickerViewalloc] initWithFrame:CGRectMake(0,420, 320, 200)];
percentPicker.delegate = self;
percentPicker.dataSource = self;
percentPicker.showsSelectionIndicator = YES;
[self.view addSubview:percentPicker];
}
- (void)viewWillAppear:(BOOL)animated {
// sets the rows to the appropriate value
// etc
}
- (void)startEditingPercentage {
[UIView beginAnimations :nilcontext:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIViewsetAnimationDuration:kPickerAnimationDuration ];
percentPicker.transform = CGAffineTransformTranslate(CGAffineTransformIdentity, 0, -220.0);
[UIViewcommitAnimations];
}
- (void)stopEditingPercentage {
NSLog(#"stopEditingPercentage");
[UIView beginAnimations :nilcontext:NULL];
[UIViewsetAnimationBeginsFromCurrentState:YES];
[UIViewsetAnimationDuration:kPickerAnimationDuration];
percentPicker.transform = CGAffineTransformIdentity;
[UIView commitAnimations];
}
#pragma mark UIPickerView delegate and dataSource methods
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return4;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return10;
}
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component {
return44;
}
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view {
UILabel *retval = (UILabel *)view;
if (!retval) {
retval= [[UILabel newLabelWithPrimaryColor :[UIColorblackColor ] selectedColor:[ UIColor blackColor] fontSize:22bold:YEStransparent:YES] autorelease];
}
retval.frame = CGRectMake(0, 0, 44, 44);
retval.textAlignment = UITextAlignmentCenter;
retval.backgroundColor = [UIColor clearColor];
retval.text = [NSStringstringWithFormat:#"%i", row];
if (component > 1 ) {
// rows 2 and 3 are decimal, white on black
retval.backgroundColor = [UIColor blackColor];
retval.textColor = [UIColor whiteColor];
}
return retval;
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
NSString *selectedValue;
selectedValue= [NSString stringWithFormat:#"%i%i.%i%i" ,[percentPickerselectedRowInComponent :0], [ percentPickerselectedRowInComponent: 1], [percentPickerselectedRowInComponent:2], [percentPickerselectedRowInComponent:3]];
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
NSString *trimmedValue = [[formatter numberFromString:selectedValue] stringValue];
percentValue.text = trimmedValue;
[formatter release];
}
As you see, I use the transform property to move the picker in and out (down) my main view; the startEditing and stopEditing methods are triggered by selection in the teble view. Yet, for the debugging purposes, I eliminated these transitions , and left the picker on top of the table, but nothing changed. I also commented the didSelect method, but this also didn't change anything.
By the way, the same picker-view construction code vorkw allright in another view of the same app.
Any suggestion?
Cheers,
You aren't really adding the picker to UITableView using the code in viewDidLoad. UITableView can only have controls/rows in UITableViewCells and these are specified in the cellForRowAtIndex method. We cannot add controls to UITableView like we do to UIView.
Try using a subclass of UIView instead and add the UITableView and the picker to this UIView subclass.
In case you want to use a UITableViewController subclass only, create a custom cell and add the picker to this custom cell. But then you won't be able to hide/unhide this cell if you add it statically. Then you'll have to use reloadData. I would suggest using the UIView subclass.