Reputation: 863
I am developing an App for iPhone (my first app) and I want to use two UIPickerView's to display some data. The first UIPickerView is going to display a list of car brands (e.g. BMW, Mercedes, Ford etc...) And the second UIPickerView is going to display models, depending on which UIPickerViewItem you select in the first UIPickerView.
The problem I have is not setting up the UIPickerView's, that's already been done.
I want to know how I can populate both PickerViews from some sort of data storage (maybe sqlite, core-data...? Not sure how neither works though) and also, the second PickerView should only be populated once the first one has selected an item, so it only shows the models for that brand.
I hope you understand, as I am really not getting how to do this (I usually only do web-developing and this is extremely easy using PHP & MySQL...) ;)
Thank's in advance! Mike
Upvotes: 2
Views: 1592
Reputation: 80265
Core data is the way to go, but the learning curve is steep. You should put quite some time aside to learn it.
Much easier and perhaps sufficient for your purposes is to work with plists. These are Apple specific xml files and very simply structured. You can edit them right in Xcode and the format is very transparent.
You could then load all the data at once from the plist and populate the second picker depending on the choice in the first.
Alternatively you could use JSON files. These are even simpler, and as a web programmer, you are probably familiar with those.
Some hints:
Your data should have this structure: array of dictionaries; each dictionary has a key for the brand and one for another array, a list of models. This subarray is a dictionary with a key for the name (and perhaps more if you need it in your app).
You can load the plist file called "Data.plist" like this (JSON is analog):
NSString *path = [[NSBundle mainBundle] pathForResource:@"Data" ofType:@"plist"];
NSArray *data = [NSArray arrayWithContentsOfFile:path];
Now you can get a list of brands like this (assuming your brand name key is "name"):
NSArray *brands = [data valueForKeyPath:@"name"];
And a list of makes for a brand:
NSArray *models = [[[data filteredArrayUsingPredicate:[NSPredicate
predicateWithFormat:@"name = %@", @"Ford"]] objectAtIndex:0]
valueForKey:@"models"]);
To react to a selection of the first picker view, make sure your view controller is the delegate of the picker views and override pickerView:didSelectRow:inComponent:
.
You can distinguish your pickers in these delegate methods by assigning tags
and checking for them in the callback methods.
Here is an example of your plist strucure:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<dict>
<key>name</key>
<string>Ford</string>
<key>models</key>
<array>
<string>Mustang</string>
<string>Capri</string>
</array>
</dict>
<dict>
<key>name</key>
<string>VW</string>
<key>models</key>
<array>
<string>Polo</string>
<string>Golf</string>
</array>
</dict>
</array>
</plist>
Hope this helps.
Upvotes: 1
Reputation: 18488
It depends on your requirement the type of data source you want. If your data source is static, and it will never change, then all you want is probably a simple NSArray you can create every time your app is started. From your requirement it looks like this is definitely what you want to do, as it is the easier way.
Whenever you create your UIPickerController or if it is an IBOUTLET do this to the ivar/property:
myPicker1.tag = 1;
myPicker2.tag = 2;
Assign a tag to distinguish them since they will be both calling the same callback methods on your delegate/datasource (your ViewController in this case)
Then since you want to take action on Picker 2 depending on the value selecting on Picker 1 you want something like this:
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
if (pickerView.tag == 1) {
//Means a value just changed on your picker 1!, update datasource for your second picker
[myPicker2 reloadComponent:0]; // This will trigger the method - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component method below
}
}
Finally implement the - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
method below method, which gets called when the picker needs to load its components, or in this case also if you call reloadComponent
You will need something like this:
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
if (pickerView.tag == 2) {
//Get appropriate value from the array and return the string for that row
MyObject *selectedObject = [myArray objectAtIndex:[pickerActivity selectedRowInComponent:0]];
//Return what you need depending on your needs.
}
}
Finally I would recommend taking a look at UIPickerView class reference
Hope that helps.
Upvotes: 1