I have 2 picker views on my story board, everything done separately. However for some reason my second viewer is exactly copying the first one.
#import <UIKit/UIKit.h>
#interface MaisOuiViewController : UIViewController <UITextFieldDelegate, UIPickerViewDataSource, UIPickerViewDelegate>
#property (strong, nonatomic) IBOutlet UIPickerView *from;
#property (strong, nonatomic) IBOutlet UIPickerView *to;
#property (strong, nonatomic) NSArray * fromlang;
#property (strong,nonatomic) NSArray * tolang;
#end
#synthesize from;
#synthesize to;
#synthesize fromlang = _fromlang;
#synthesize tolang= _tolang;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.inWord.delegate = self;
//Load NSArray fromlang
_fromlang= [[NSArray alloc] initWithObjects:#"English",#"Spanish",#"German", nil];
//Load NSArray tolang
_tolang= [[NSArray alloc] initWithObjects:#"Hindi",#"Chinese",#"Check", nil];
}
#pragma mark - UIPickerView Methods
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 1;
}
- (NSInteger)numberOfComponentsInPickerView1:(UIPickerView *)pickerView1
{
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return _fromlang.count;
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
return [_fromlang objectAtIndex:row];
}
- (NSInteger)pickerView1:(UIPickerView *)pickerView1 numberOfRowsInComponent1:(NSInteger)component1
{
return _tolang.count;
}
- (NSString *)pickerView1:(UIPickerView *)pickerView1 titleForRow:(NSInteger)row forComponent1:(NSInteger)component1
{
return [_tolang objectAtIndex:row];
}
#end
Can somebody please point out where am I going wrong ?
Thanks
The UIPickerViews from and to looks same because the delegate and datasource methods are same. iOS will call only the methods which are mentioned below as per the apple iOS documents refers
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return _fromlang.count;
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
return [_fromlang objectAtIndex:row];
}
You can instead set tag for to and from and use the code mentioned below
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.inWord.delegate = self;
//Set tags to differentiate
from.tag=1;
to.tag=2;
//Load NSArray fromlang
_fromlang= [[NSArray alloc] initWithObjects:#"English",#"Spanish",#"German", nil];
//Load NSArray tolang
_tolang= [[NSArray alloc] initWithObjects:#"Hindi",#"Chinese",#"Check", nil];
}
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
if(pickerView.tag==1)
{
return 1;
}
else
{
return 1;
}
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
if(pickerView.tag==1)
{
return _fromlang.count;
}
else
{
return _tolang.count;
}
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
if(pickerView.tag==1)
{
return [_fromlang objectAtIndex:row];
}
else
{
return [_tolang objectAtIndex:row];
}
}
Hope this will help.
If you have two buttons to show that then take one integer variable and set some value or take BOOL value to make the difference or set the tag of your picker then after based on your condition call your array in picker view.
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
NSString *titleString;
if (currentSelectedDropDown == 1) {
AIFillAccountTypeParserModel *modal = [[AIFillAccountTypeParserModel alloc]init];
if (isSearching) {
modal = [filteredArray objectAtIndex:row];
}else{
modal = [accountTypesPickerArray objectAtIndex:row];
}
titleString = modal.accountType;
accountTypeTxtField.text = titleString;
}
else if(currentSelectedDropDown == 2) {
AIFillRatingParserModel *modal = [[AIFillRatingParserModel alloc]init];
if (isSearching) {
modal = [filteredArray objectAtIndex:row];
}else{
modal = [accountTypesPickerArray objectAtIndex:row];
}
titleString = modal.rating_Description;
ratingTxtField.text = titleString;
}
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
if (currentSelectedDropDown == 1) {
AIFillAccountTypeParserModel *modal = nil;
if (isSearching) {
modal = [filteredArray objectAtIndex:row];
}
else{
modal = [accountTypesPickerArray objectAtIndex:row];
}
NSString *titleString = modal.accountType;
accountTypeTxtField.text = titleString;
accountTypeId = modal.accountId;
NSUserDefaults *accountType = [NSUserDefaults standardUserDefaults];
[accountType setObject:modal.accountId forKey:#"SavedaccountType"];
}
else if (currentSelectedDropDown == 2) {
AIFillOwnershipParserModel *modal = nil;
if (isSearching) {
modal = [filteredArray objectAtIndex:row];
}
else{
modal =[accountTypesPickerArray objectAtIndex:row];
}
NSString *titleString = modal.ownership;
ownershipTypeTxtField.text = titleString;
ownerShipId = modal.ownerShipID;
}
}
This is just a example to make you understand
Related
I'm new to iOS programming.
Recently, I'm trying to make a UIPickerView as an inputView in UITextfield.
The data in UIPickerView is about all the iOS built-in fonts.
So I want to make two components in UIPickerView: the first is familyType, and the second is all the fonts in that familyType.
I simulate the code from this answer, but I meet some problem I can't solve. Any help is welcome!
My question is here:
Why rowOneSelected in this function always get 0 first, even I use selectedRowInComponent in advance?
// The number of rows of data
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
if(component == 0)
{
return _fontTypeArray.count;
}
else
{
NSInteger rowOneSelected = [_pickerFont selectedRowInComponent:0];
FontType *temp = _fontTypeArray[rowOneSelected];
NSLog(#"%ld", (long)rowOneSelected); // I use this to debug, and there is a main question: why every time it logs 0 first?
return temp.font.count;
}
}
All my relative code is here:
In ViewController.h:
#import <UIKit/UIKit.h>
#import "MenuLayerTwoPlusThree.h"
#interface ViewController : UIViewController
#property MenuLayerTwoPlusThree *layerTwoPlusThree;
- (void)createLayerTwoPlusThree;
#end
In ViewController.m:
- (void)viewDidLoad {
[super viewDidLoad];
[self createLayerTwoPlusThree];
}
- (void)createLayerTwoPlusThree
{
_layerTwoPlusThree = [MenuLayerTwoPlusThree alloc];
[_layerTwoPlusThree createFontArray];
[_layerTwoPlusThree createSelectPanel];
}
In FontType.h:
#ifndef FontType_h
#define FontType_h
#import <Foundation/Foundation.h>
#interface FontType : NSObject
#property NSString *familyName;
#property NSMutableArray *font;
#end
#endif /* FontType_h */
In FontType.m:
#import <Foundation/Foundation.h>
#import "FontType.h"
#implementation FontType
#synthesize familyName;
#synthesize font;
#end
In MenuLayerTwoPlusThree.h:
#ifndef MenuLayerTwoPlusThree_h
#define MenuLayerTwoPlusThree_h
#import <UIKit/UIKit.h>
#import "FontType.h"
#interface MenuLayerTwoPlusThree : NSObject<UITextFieldDelegate, UIPickerViewDataSource, UIPickerViewDelegate>
#property UITextField *textFieldFont;
#property NSMutableArray *fontTypeArray;
#property UIPickerView *pickerFont;
#property UIBarButtonItem *doneButton;
#property UIBarButtonItem *spaceButton;
#property UIBarButtonItem *cancelButton;
#property UIToolbar *toolBar;
#property NSArray *toolBarItems;
#property NSInteger familyType;
#property NSInteger fontType;
#property NSString *fontName;
- (void)createFontArray;
- (IBAction)pickerViewButtonClicked:(id)sender;
#end
In MenuLayerTwoPlusThree.m
- (void)createFontArray
{
_fontTypeArray = [[NSMutableArray alloc]initWithCapacity:80];
int number = 0;
for(NSString* family in [UIFont familyNames])
{
//NSLog(#"%#", family);
//number++;
FontType *temp = [[FontType alloc]init];
temp.familyName = family;
temp.font = [[NSMutableArray alloc]init];
int flag = 0;
for(NSString* name in [UIFont fontNamesForFamilyName:family])
{
//NSLog(#" %#", name);
//number++;
flag++;
[temp.font addObject:name];
}
// add Heiti SC, Heiti TC, Telugu Sangam MN, and Bangla Sangam MN to font array
if(flag == 0)
{
[temp.font addObject:family];
}
[_fontTypeArray addObject:temp];
}
// print all fonts test
for(FontType *x in _fontTypeArray)
{
number++;
NSLog(#"%#", x.familyName);
for(NSString *y in x.font)
{
//number++;
NSLog(#"\t%#", y);
}
}
NSLog(#"//////////////////////////////");
NSLog(#"%d", number);
}
- (void)createSelectPanel
{
[self createSelectPanelForPancel1];
[self createSelectPanelForPancel2];
[self createSelectPanelForFont];
[self createSelectPanelForShape];
[self createSelectPanelForEraser];
}
- (void)createSelectPanelForFont
{
_textFieldFont = [[UITextField alloc]initWithFrame:CGRectMake(19, 148, 150, 12)];
[_textFieldFont setBackground:[UIImage imageNamed:#"font-type-bar.png"]];
_textFieldFont.rightViewMode = UITextFieldViewModeAlways;
_textFieldFont.delegate = self;
[_textFieldFont setPlaceholder:#"Heiti TC"];
_textFieldFont.font = [_textFieldFont.font fontWithSize:10 * _aspectRatio];
// resize right view image
UIImageView *rightViewImage = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 12 * _aspectRatio, 12 * _aspectRatio)];
[rightViewImage setImage:[UIImage imageNamed:#"font-type-bar-roll.png"]];
_textFieldFont.rightView = rightViewImage;
_pickerFont = [[UIPickerView alloc]init];
_pickerFont.dataSource = self;
_pickerFont.delegate = self;
_pickerFont.showsSelectionIndicator = YES;
_doneButton = [[UIBarButtonItem alloc]initWithTitle:#"Done" style:UIBarButtonItemStyleDone target:self action:#selector(pickerViewButtonClicked:)];
_spaceButton = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
_cancelButton = [[UIBarButtonItem alloc]initWithTitle:#"Cancel" style:UIBarButtonItemStylePlain target:self action:#selector(pickerViewButtonClicked:)];
_toolBar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 45)];
[_toolBar setBarStyle:UIBarStyleDefault];
_toolBarItems = [NSArray arrayWithObjects:_cancelButton, _spaceButton, _doneButton, nil];
[_toolBar setItems:_toolBarItems];
_textFieldFont.inputView = _pickerFont;
_textFieldFont.inputAccessoryView = _toolBar;
if (#available(iOS 9.0, *)) {
_textFieldFont.inputAssistantItem.leadingBarButtonGroups = #[];
} else {
// Fallback on earlier versions
}
if (#available(iOS 9.0, *)) {
_textFieldFont.inputAssistantItem.trailingBarButtonGroups = #[];
} else {
// Fallback on earlier versions
}
// I want to add these codes to select row in advanced to make sure first time NSLog will print 9, but it doesn't work.
// [_pickerFont reloadAllComponents];
// _familyType = 9;
// _fontType = 0;
// _fontName = #"Heiti TC";
// [_pickerFont selectRow:_familyType inComponent:0 animated:YES];
[_selectPanelFontView addSubview:_textFieldFont];
}
And this is the delegate, which I am written in the MenuLayerTwoPlusThree.m:
// The number of columns of data
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 2;
}
// The number of rows of data
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
if(component == 0)
{
return _fontTypeArray.count;
}
else
{
NSInteger rowOneSelected = [_pickerFont selectedRowInComponent:0];
FontType *temp = _fontTypeArray[rowOneSelected];
NSLog(#"%ld", (long)rowOneSelected); // I use this to debug, and there is a main question: why every time it logs 0 first?
return temp.font.count;
}
}
// The data to return for the row and component (column) that's being passed in
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
if(component == 0)
{
FontType *temp = _fontTypeArray[row];
return temp.familyName;
}
else
{
NSInteger rowOneSelected = [_pickerFont selectedRowInComponent:0];
FontType *temp = _fontTypeArray[rowOneSelected];
return [temp.font objectAtIndex:row];
}
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
if(component == 0)
{
[_pickerFont reloadComponent:1];
}
// This block is moved to pickerViewButtonClicked (sender == _doneButton)
// else
// {
// NSInteger rowOneSelected = [_pickerFont selectedRowInComponent:0];
// FontType *temp = _fontTypeArray[rowOneSelected];
// [_textFieldFont setText:temp.font[row]];
// }
}
- (IBAction)pickerViewButtonClicked:(id)sender
{
if(sender == _doneButton)
{
// Save value when I clicked the done button.
_familyType = [_pickerFont selectedRowInComponent:0];
_fontType = [_pickerFont selectedRowInComponent:1];
// NSLog(#"family: %ld", _familyType);
// NSLog(#"font: %ld", _fontType);
FontType *temp = _fontTypeArray[_familyType];
_fontName = temp.font[_fontType];
[_textFieldFont setText:_fontName];
// NSLog(#"font name: %#", _fontName);
[_textFieldFont endEditing:YES];
}
else if(sender == _cancelButton)
{
[_textFieldFont endEditing:YES];
// I want to turn back to the last selected value when I clicked the cancel button.
[_pickerFont reloadAllComponents];
[_pickerFont selectRow:_familyType inComponent:0 animated:NO];
[_pickerFont selectRow:_fontType inComponent:1 animated:NO];
}
}
It really seems that when the UIPickerView appears as an inputView after you have selected row 9 in component 0, the selectedRowInComponent: 0 returns 0 in numberOfRowsInComponent: 1, but then returns 9 in titleForRow: row forComponent: 1.
I don't think you are doing anything wrong, so it looks like a bug in UIKit.
As a workaround, I suggest you don't ask the picker view for the selected row, but track the selected row yourself (initialize your own variable in your view controller and update it in didSelectRow: row inComponent: 0)
Sorry, I forgot to post my solution.
I use _fontTypeIsFirst to see if UIPickerView has been selected or not.
When you roll the picker view, you should set _fontTypeIsFirst to NO and reload component 1, so it can return to row 0 in component 1 as usual.
Here is my code:
Some delegates:
// The number of columns of data
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 2;
}
// The number of rows of data
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
if(component == 0)
{
return _fontTypeArray.count;
}
else
{
NSInteger rowOneSelected;
if (_fontTypeIsFirst == YES)
{
rowOneSelected = _selectedRow;
}
else
{
rowOneSelected = [_pickerFont selectedRowInComponent:0];
}
FontType *temp = _fontTypeArray[rowOneSelected];
return temp.font.count;
}
}
// The data to return for the row and component (column) that's being passed in
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
if(component == 0)
{
FontType *temp = _fontTypeArray[row];
return temp.familyName;
}
else
{
NSInteger rowOneSelected;
if (_fontTypeIsFirst == YES)
{
rowOneSelected = _selectedRow;
}
else
{
rowOneSelected = [_pickerFont selectedRowInComponent:0];
}
FontType *temp = _fontTypeArray[rowOneSelected];
return [temp.font objectAtIndex:row];
}
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
_fontTypeIsFirst = NO;
if(component == 0)
{
[_pickerFont reloadComponent:1];
}
}
And this is action of done and cancel button:
- (IBAction)pickerViewButtonClicked:(id)sender
{
if(sender == _doneButton)
{
_selectedRow = [_pickerFont selectedRowInComponent:0];
_familyType = [_pickerFont selectedRowInComponent:0];
_fontType = [_pickerFont selectedRowInComponent:1];
FontType *temp = _fontTypeArray[_familyType];
_fontName = temp.font[_fontType];
[_textFieldFont setText:_fontName];
[_textFieldFont endEditing:YES];
_fontTypeIsFirst = YES;
}
else if(sender == _cancelButton)
{
[_textFieldFont endEditing:YES];
_fontTypeIsFirst = YES;
[_pickerFont selectRow:_familyType inComponent:0 animated:NO];
[_pickerFont selectRow:_fontType inComponent:1 animated:NO];
}
}
And you can add codes like this to select default value of picker view in viewDidLoad or some place:
_fontTypeIsFirst = YES;
_selectedRow = 9;
_familyType = 9;
_fontType = 0;
_fontName = #"Heiti TC";
[_pickerFont selectRow:_familyType inComponent:0 animated:NO];
[_pickerFont selectRow:_fontType inComponent:1 animated:NO];
Hello guys thanks for reading this question. So i have been stuck on this issue for a while now and need a bit of help. I am attempting to implement multiple pickers in IOS but they do not come out as planned. I successfully done one picker by itself but attempting to add another one in the same view i have ran into problems.
So at first i thought it was a problem to do with this line of code. But when using the return 1: it would just return the same ui picker twice. And return 2 returns the same issue as above but with two rows.
-(NSInteger)numberOfComponentsInPickerView: (UIPickerView *)pickerView {
/*
return 1;
*/
if(pickerView == _picker) {
return _colourSourceArray.count;
} else if(_picker == _mustachepicker) {
return _mustacheArray.count;
}
}
Both of my datasources are linked to the same view, would this be causing the problem?
What my .h looks like:
////// Frame Colour Picker
#property (strong, nonatomic)NSArray *colourSourceArray;
#property (strong, nonatomic)NSString *selectedcolour;
#property (weak, nonatomic) IBOutlet UIPickerView *picker;
////// Mustahce Picker
#property (weak, nonatomic) IBOutlet UIPickerView *mustachepicker;
#property (weak, nonatomic) NSArray *mustacheArray;
#property (weak,nonatomic) NSString *selectedMostache;
/////////////////////////
And my .m methods:
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
NSInteger comp = 0;
if(_picker == _mustachepicker){
comp= _mustacheArray.count;
} else if(pickerView == _picker) {
comp= _colourSourceArray.count;
}
return comp;
}
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
NSString *title;
if(_picker == _mustachepicker){
title= _mustacheArray[row];
} else if(pickerView == _picker){
title = _colourSourceArray[row];
}
return title;
}
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
if(_picker == _mustachepicker){
NSString *mustacheString= _mustacheArray[row];
NSLog(mustacheString);
_selectedMostache=mustacheString;
} else if(pickerView == _picker){
NSString *resultString = _colourSourceArray[row];
_selectedcolour= resultString;
NSLog(resultString);
}
NSLog(_selectedcolour);
NSLog(_selectedMostache);
}
Any help would be appreciated :)
As you have created two different pickers, then why are you setting the tag to the pickers just compare the UIPicker in there DataSource and Delegate methods like this
-(NSInteger)numberOfComponentsInPickerView: (UIPickerView *)pickerView {
if(pickerView == _picker) {
return _colourSourceArray.count;
} else if(_picker == _mustachepicker) {
return _mostacheArray.count;
}
}
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
NSInteger comp = 0;
if(_picker == _mustachepicker){
comp= _mostacheArray.count;
} else if(pickerView == _picker) {
comp= _colourSourceArray.count;
}
return comp;
}
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow(NSInteger)row forComponent:(NSInteger)component {
NSString *title;
if(_picker == _mustachepicker){
title= _mostacheArray[row];
} else if(pickerView == _picker){
title = _colourSourceArray[row];
}
return title;
}
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
if(_picker == _mustachepicker){
NSString *mostacheString= _mostacheArray[row];
NSLog(mostacheString);
_selectedMostache=mostacheString;
} else if(pickerView == _picker){
NSString *resultString = _colourSourceArray[row];
_selectedcolour= resultString;
NSLog(resultString);
}
NSLog(_selectedcolour);
NSLog(_selectedMostache);
}
I'm trying to build a screen with two dependent components in a picker view. I connected picker with property, dataSource and delegate with yellow button of view controller on the top of the scene, and I also connected button action with buttonPressed method.
After building I receive white screen with empty picker without data. Why does it happen?
#import "BIDDependentComponentPickerViewController.h"
#define kStateComponent 0
#define kZipComponent 1
#interface BIDDependentComponentPickerViewController ()
#property (strong, nonatomic) NSDictionary *stateZips;
#property (strong, nonatomic) NSArray *states;
#property (strong, nonatomic) NSArray *zips;
#property (weak, nonatomic) IBOutlet UIPickerView *dependentPicker;
#end
#implementation BIDDependentComponentPickerViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
NSBundle *bundle = [NSBundle mainBundle];
NSURL *plistURL = [bundle URLForResource:#"statedictionary"
withExtension:#"plist"];
self.stateZips = [NSDictionary dictionaryWithContentsOfURL:plistURL];
NSArray *allStates = [self.stateZips allKeys];
NSArray *sortedStates = [allStates sortedArrayUsingSelector:
#selector(compare:)];
self.states = sortedStates;
NSString *selectedState = self.states[0];
self.zips = self.stateZips[selectedState];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
}
- (IBAction)buttonPressed:(id)sender {
NSInteger stateRow = [self.dependentPicker
selectedRowInComponent:kStateComponent];
NSInteger zipRow = [self.dependentPicker
selectedRowInComponent:kZipComponent];
NSString *state = self.states[stateRow];
NSString *zip = self.zips[zipRow];
NSString *title = [[NSString alloc] initWithFormat:
#"You selected zip code %#.", zip];
NSString *message = [[NSString alloc] initWithFormat:
#"%# is in %#", zip, state];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title
message:message
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 2;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView
numberOfRowsInComponent:(NSInteger)component {
if (component == kStateComponent) {
return [self.states count];
} else {
return [self.zips count];
}
}
- (NSString *)pickerView:(UIPickerView *)pickerView
titleForRow:(NSInteger)row
forComponent:(NSInteger)component
{
if (component == kStateComponent) {
return self.states[row];
} else {
return self.zips[row];
}
}
- (void)pickerView:(UIPickerView *)pickerView
didSelectRow:(NSInteger)row
inComponent:(NSInteger)component
{
if (component == kStateComponent) {
NSString *selectedState = self.states[row];
self.zips = self.stateZips[selectedState];
[self.dependentPicker reloadComponent:kZipComponent];
[self.dependentPicker selectRow:0
inComponent:kZipComponent
animated:YES];
} }
#end
Make sure you have added statedictionary file in bundle.
Also you can Log the array/dictionary to check if values are there.
I am dynamically adding data to a pickerview as information becomes available. Though I am adding data to my array and calling [picker reloadAllComponents] the pickerview does not show any data.
I also noticed that neither of the following Delegates are getting called:
- (NSString*)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
-(UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view{
Here is my viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_pickerData = [[NSMutableArray alloc] init];
_ActiveDevice = [[NSString alloc]init];
// Connect data
self.DevicePicker.dataSource = self;
self.DevicePicker.delegate = self;
}
Here is the method that loads my hidden PickerView (I have it defaulted to hide until a button is pushed)
- (IBAction)FanDrop:(id)sender {
[self printFromCoreData];
[self.DevicePicker reloadAllComponents];
if (_DeviceBox) _DeviceBox.hidden = !_DeviceBox.hidden;
}
I load the array the is the datasource for the DevicePicker using what is found in coredata This all seems to work as I can find information when logging what is in the array. Also when clicking the accept button even though nothing is showing the correct data gets loaded thus telling me that everything but the display portion of my code is working correct.
Any insight - I'm open to try almost anything.
After one comment I realized I neglected to include, in my question, the delegates. SO here they are:
// The number of columns of data
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 1;
}
// The number of rows of data
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return _pickerData.count;
}
// The data to return for the row and component (column) that's being passed in
- (NSString*)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
//return _pickerData[row];
return [_pickerData objectAtIndex:row];
}
-(UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view{
return [_pickerData objectAtIndex:row];
}
Here is how I am adding the array pickerData:
#interface CMTViewController ()
{
NSMutableArray *_pickerData;
}
Here is the CoreData method I use to load _pickerData:
-(void)printFromCoreData{
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"DeviceData"];
self.devices = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
for (NSManagedObject *info in _devices) {
NSString *item = [NSString stringWithFormat:#"%1$# %2$#",[info valueForKey:#"name"], [info valueForKey:#"ipAddress"]];
if (![_pickerData containsObject:item]) {
[_pickerData addObject:item];
}
}
NSLog(#"_pickerData length %lu", (unsigned long)[_pickerData count]);
[self.DevicePicker reloadAllComponents];
}
Here is the view of what happens in the simulator (or on my phone) when I push the fans button:
Fuji sir,
My recommendation would be as follows based on our conversation:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self printFromCoreData];
_ActiveDevice = [[NSString alloc]init];
// Connect data
self.DevicePicker.dataSource = self;
self.DevicePicker.delegate = self;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return _pickerData.count;
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 1;
}
- (NSString*)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
return _pickerData[row];
}
And don't include reusingView unless you want to change the layout and add custom labels etc
You need to add following methods
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return _pickerData.count;
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent: (NSInteger)component{
return [_pickerData objectAtIndex:row];
}
}
Am trying to set the width of two components in a picker view. They are of equal width, and I want to make one wider. For this reason, I have used the
(CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component
method.
My problem is that after I have set the method, I only get one component back instead of two. I have checked to see if I have written the method wrong, but can't find anything wrong.
Any idea what's wrong?
Here is the code:
#import "BIDDependentComponentPickerViewController.h"
#implementation BIDDependentComponentPickerViewController
#synthesize picker;
#synthesize stateZips;
#synthesize states;
#synthesize zips;
- (IBAction)buttonPressed:(id)sender
{
NSInteger stateRow = [picker selectedRowInComponent:kStateComponent];
NSInteger zipRow = [picker selectedRowInComponent:kZipComponent];
NSString *state = [self.states objectAtIndex:stateRow];
NSString *zip = [self.zips objectAtIndex:zipRow];
NSString *title= [[NSString alloc] initWithFormat:#"You selected zip code %#.", zip];
NSString *message = [[NSString alloc] initWithFormat:#"#% is in #%", zip, state];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title
message:message
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
NSBundle *bundle = [NSBundle mainBundle];
NSURL *plistURL = [bundle URLForResource:#"statedictionary" withExtension:#"plist"];
NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfURL:plistURL];
self.stateZips = dictionary;
NSArray *components = [self.stateZips allKeys];
NSArray *sorted = [components sortedArrayUsingSelector:#selector(compare:)];
self.states = sorted;
NSString *selectedState = [self.states objectAtIndex:0];
NSArray *array = [stateZips objectForKey:selectedState];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.picker = nil;
self.stateZips = nil;
self.states = nil;
self.zips = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark
#pragma mark Picker Data Source Methods
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 2;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
if (component == kStateComponent) {
return [self.states count];
return [self.zips count];
}
}
#pragma mark Picker Delegate Methods
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
if(component == kStateComponent)
return [self.states objectAtIndex:row];
return [self.zips objectAtIndex:row];
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
if (component == kStateComponent)
{
NSString *selectedState = [self.states objectAtIndex:row];
NSArray *array = [stateZips objectForKey:selectedState];
self.zips = array;
[picker selectRow:0 inComponent:kZipComponent animated:YES];
[picker reloadComponent:kZipComponent];
}
}
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component
{
if (component == kZipComponent) {
return 90;
return 200;
}
}
#end
The line:
return 200;
is never reached. It should be outside the IF statement like so:
if (component == kZipComponent) {
return 90.0;
}
return 200.0;
Otherwise, your method does not return a value for any component OTHER than kZipComponent (so the width of other components is 0).