1

I don't have much experience in programming, so here is my question:

I'm trying to write a converter app. At the end, you can enter a number. Then I have a two component UIPickerView. With the first component, you select the input format (e.x. °Celcius). With the second component, you select the output format (e.x. °Fahrenheit), in order to convert °Celcius into °Fahrenheit.

But I want to add more units (weight, energy etc.). I want them to display on a UITableView. If I select a certain cell in the UITableView, the UIPickerView has to update its delegate. More precisely, the array in which I have the names of the units (e.x. eV, Joule, cal, erg, etc...) must be somehow implemented in the detailViewController (where I have my UIPickerView).

Here's my code:

ViewController.h

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController
<UITableViewDataSource,UITableViewDelegate,UIPickerViewDataSource,UIPickerViewDelegate>

@property (strong,nonatomic) IBOutlet UIPickerView *EinheitenPicker;
@property (weak,nonatomic) IBOutlet UITableView *EinheitenTableView;

@end

ViewController.m

#import "ViewController.h"


@interface ViewController ()
{
    NSArray *EinheitenNameArray;
}
@end

@implementation ViewController
@synthesize EinheitenPicker,EinheitenTableView;
- (void)viewDidLoad
{
    [super viewDidLoad];

    EinheitenNameArray=[NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"AlleEinheiten" ofType:@"plist"]];

    [self.EinheitenTableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:YES scrollPosition:UITableViewScrollPositionTop];

    [self.EinheitenTableView.delegate tableView:self.EinheitenTableView didSelectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}

#pragma mark UItableView Delegate
- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return EinheitenNameArray.count;
}

- (UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdentifier=@"CellId";
    UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    if(cell==nil) {
        cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    }

    cell.textLabel.text=[[EinheitenNameArray objectAtIndex:indexPath.row] objectForKey:@"Titel"];

    return cell;
}


- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

    //NSLog(@"Chosen:%@",self.EinheitenPicker);

    [self.storyboard instantiateViewControllerWithIdentifier:@"TestId"];

    [self.EinheitenPicker reloadAllComponents];
}

#pragma mark UIPickerView Methods

- (NSInteger) numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
    return 2;
}

- (NSInteger) pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
    NSIndexPath *selectedIndexPath=[self.EinheitenTableView indexPathForSelectedRow];
    NSArray *units=[[EinheitenNameArray objectAtIndex:selectedIndexPath.row] objectForKey:@"Einheiten"];

    if (component == 0) {
        return units.count;
    }

    return units.count;   
}

- (NSString*) pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
    NSIndexPath *selectedIndexPath=[self.EinheitenTableView indexPathForSelectedRow];
    NSArray *units=[[EinheitenNameArray objectAtIndex:selectedIndexPath.row] objectForKey:@"Einheiten"];
    return [units objectAtIndex:row];
}

@end

1 Answers1

3

If I am not wrong you are looking for something like this.

enter image description here

To have it so you must implement UIPickerView methods as follows

-(NSInteger) numberOfComponentsInPickerView:(UIPickerView *)pickerView{
    return 1;
}

-(NSInteger) pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{

    NSIndexPath *selectedIndexPath=[self.unitsTableView indexPathForSelectedRow];
    NSArray *units=[[unitDataArray objectAtIndex:selectedIndexPath.section] objectForKey:@"units"];
    return units.count;
}

-(NSString*) pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{
    NSIndexPath *selectedIndexPath=[self.unitsTableView indexPathForSelectedRow];
    NSArray *units=[[unitDataArray objectAtIndex:selectedIndexPath.section] objectForKey:@"units"];
    return [units objectAtIndex:row];
}

In UITableView Delegate you can reload the picker View as follows.

-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    [self.unitPicker reloadAllComponents];
}

To create the items for Table which has components as well units , you can use .plist file as follows

enter image description here

To help you with UITableView Methods I am adding the required code.

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    unitDataArray=[NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:<Name of plist File> ofType:@"plist"]];
    [self.unitsTableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:YES scrollPosition:UITableViewScrollPositionTop];
    [self.unitsTableView.delegate tableView:self.unitsTableView didSelectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
}

-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView{
    return unitDataArray.count;
}

-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    NSDictionary *unitData=[unitDataArray objectAtIndex:section];
    return [[unitData objectForKey:@"units"] count];
}

-(UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    static NSString *cellIdentifier=@"CellId";
    UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    if(cell==nil){
        cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    }
    cell.textLabel.text=[[[unitDataArray objectAtIndex:indexPath.section] objectForKey:@"units"] objectAtIndex:indexPath.row];

    return cell;
}

-(NSString*) tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
    NSDictionary *unitData=[unitDataArray objectAtIndex:section];
    return [unitData objectForKey:@"title"];
}


-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    [self.unitPicker reloadAllComponents];
}

CHANGES If you want it to show as displayed below, minor tweaks to my code is required.

enter image description here

@implementation ViewController
@synthesize unitPicker,unitsTableView;
- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    unitDataArray=[NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"AllUnits" ofType:@"plist"]];
    [self.unitsTableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:YES scrollPosition:UITableViewScrollPositionTop];
    [self.unitsTableView.delegate tableView:self.unitsTableView didSelectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark UItableView Delegate
-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView{
    return 1;//Changes 1
}

-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return unitDataArray.count;//Changes 2
}

-(UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    static NSString *cellIdentifier=@"CellId";
    UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    if(cell==nil){
        cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    }
    cell.textLabel.text=[[unitDataArray objectAtIndex:indexPath.row] objectForKey:@"title"];

    return cell;
}


-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    [self.unitPicker reloadAllComponents];
}

#pragma mark UIPicker View Methods

-(NSInteger) numberOfComponentsInPickerView:(UIPickerView *)pickerView{
    return 1;//Changes 3
}

-(NSInteger) pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{

    NSIndexPath *selectedIndexPath=[self.unitsTableView indexPathForSelectedRow];
    NSArray *units=[[unitDataArray objectAtIndex:selectedIndexPath.row] objectForKey:@"units"];//Changes 4
    return units.count;
}

-(NSString*) pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{
    NSIndexPath *selectedIndexPath=[self.unitsTableView indexPathForSelectedRow];
    NSArray *units=[[unitDataArray objectAtIndex:selectedIndexPath.row] objectForKey:@"units"];//Changes 5
    return [units objectAtIndex:row];
}




@end

Header File is quite simple too.

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController <UITableViewDataSource,UITableViewDelegate,UIPickerViewDataSource,UIPickerViewDelegate>
@property (weak,nonatomic) IBOutlet UIPickerView *unitPicker;
@property (weak,nonatomic) IBOutlet UITableView *unitsTableView;
@end

Please find the Demo project here

NNikN
  • 3,720
  • 6
  • 44
  • 86
  • Thank you so much! Could you please show the header-file, as I have some troubles with the implementation. @andyPaul – user2401473 May 22 '13 at 13:48
  • Ur welcome, let me know if you need anything else. If have you any troubles please ask. – NNikN May 22 '13 at 17:12
  • Thanks for answering! I still have 3 small questions: - Is there no need to implement the unitDataArray somewhere (as it is not in the h-file)? - How do you connect everything in the xib-file? - And would it also be possible to create everything using Storyboard, where the UIPicker and the UITableView are not in the same View? You're a great help to me, thanks a lot and sorry for being an absolut beginner, I started 2 month ago and for me it's very complicated! @andyPaul – user2401473 May 22 '13 at 20:15
  • Ur welcome Mr. absolute beginner , i have now attached a demo project for you with this email, hope that helps you to learn things on connection and other stuff. – NNikN May 23 '13 at 17:50
  • I still have a tiny problem: I want the UIPickerView in another `ViewController`. Do I have to use a `prepareForSegue`-method? @andyPaul – user2401473 May 28 '13 at 17:39
  • You can use prepareForSegue but instead of that use [self.storyboard instantiateViewControllerWithIdentifier:@"View Controller Storyboard Id"]; This will get you the UIViewController in storyboard file. Once you have it set the frame of the view and add then add it to view of your current controller. – NNikN May 29 '13 at 12:08
  • no push-segue is not required here now. just drag a UIViewController in storyboard, set the StoryboardId thats it. Use that id in [self.storyboard instantiateViewControllerWithIdentifier:@""] – NNikN May 29 '13 at 16:25
  • is there no simple solution? @andyPaul – user2401473 Jun 01 '13 at 07:19
  • I don't know, why you are not able to get it,As commented before You are not doing what i have said. Repeating Again "[self.storyboard instantiateViewControllerWithIdentifier:@"View Controller Storyboard Id"], this will give you are UIViewController. A UIViewController has a UIView , you set the frame of a UIView object. and Then add it to your current ViewController(view in ViewController.m)".. You have just obtained a UIViewController from [self.storyboard instantiateViewControllerWithIdentifier:@"TestId"] but not using it. – NNikN Jun 01 '13 at 08:35
  • could you upload a demo-file, as I have some tremendous problems with the Interface-Builder a linking everything together? @andyPaul – user2401473 Jun 01 '13 at 11:37
  • I searched for hours and I haven't seen any solution to my problem: I just want that the UITableView and the UIPickerView are NOT in the same View. Is there a simple solution? @andyPaul – user2401473 Jun 29 '13 at 20:26