How to Setup a Second Component with a Uipickerview

How do I setup a second component with a UIPickerView

Thanks to @Bluehound for pointing me in the right direction. I had to look at some objective-c on GitHub to find out exactly how to do it, this is the answer I was looking for:

TimeViewController:

class TimeViewController: UIViewController, UIPickerViewDelegate {

@IBOutlet weak var timeSegueLabel: UILabel!

let minutes = Array(0...9)
let seconds = Array(0...59)

var recievedString: String = ""

func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {

return 2

}

func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
//row = [repeatPickerView selectedRowInComponent:0];
var row = pickerView.selectedRowInComponent(0)
println("this is the pickerView\(row)")

if component == 0 {
return minutes.count
}

else {
return seconds.count
}

}

func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {

if component == 0 {
return String(minutes[row])
} else {

return String(seconds[row])
}
}

override func viewDidLoad() {
super.viewDidLoad()

timeSegueLabel.text = recievedString

}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()

}

This is the result:

Sample Image

UIPickerView multi components in swift

Try do like this. I dont know what you exactly want. But it seems you want to reload the components on row selection of first component. If this is the requirement then this code will work.

func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 2
}

func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
//row = [repeatPickerView selectedRowInComponent:0];
var row = pickerView.selectedRowInComponent(0)
println("this is the pickerView\(row)")

if component == 0 {
return cubesToWorkWith.count
}
else {
return firstArray.count
}
}

func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {

if component == 0 {
return cubesToWorkWith[row]
} else {
return getArrayForRow(row)[row]
}
}

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if component == 0 {
pickerView.reloadComponent(1)
}
}

func getArrayForRow(row: Int) -> [String] {
switch row { // check if 2*2 0r 3*3
case 0:
return firstArray
case 1:
return secondArray
// and so on...
default:
return []
}
}

Correct work with UIPickerVIew with two numbers components

Maybe something like this if I understand your question correctly

 func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if component == 0 {
componentOne = numbers.filter { (a) -> Bool in
return a > numbers[row]
}
pickerView.reloadComponent(1)
pickerView.selectRow(0, inComponent: 1, animated: true)
}
}

And use componentOne in the dataSource methods.

I'm not sure what you have to do in the edge case but you can choose.

How to load data in second component of UIPickerView from first component selection

This has to be simpler than what you're doing. Let me show you how I did it in a quick example:

@interface ViewController () <UIPickerViewDataSource, UIPickerViewDelegate>

@property (strong, nonatomic) IBOutlet UIPickerView *pickerView;

@property (nonatomic, strong) NSArray *leftComponentItems; // Items from this array will populate the left component
@property (nonatomic, strong) NSArray *rightComponentItemsA; // Items from this array will populate the right component, when the 1st row of the left component is selected
@property (nonatomic, strong) NSArray *rightComponentItemsB; // Items from this array will populate the right component, when the 2nd row of the left component is selected

@property (nonatomic, assign) NSInteger selectedLeftRow; // This keeps track of the selected row on the left component (you could take that from the datasource as well)

@end

and then in your implementation:

@implementation ViewController 

- (void)viewDidLoad {
[super viewDidLoad];

self.selectedLeftRow = 0;

self.leftComponentItems = @[@"first", @"second"];

self.rightComponentItemsA = @[@"A1", @"A2", @"A3", @"A4", @"A5"];
self.rightComponentItemsB = @[@"B1", @"B2", @"B3", @"B4", @"B5", @"B6", @"B7"];
}

-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 2; // We have left & right components, this will always be "2"
}

-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
if (component == 0) {
return self.leftComponentItems.count;
}

if (component == 1) {
if (self.selectedLeftRow == 0) {
return self.rightComponentItemsA.count;
} else {
return self.rightComponentItemsB.count;
}
}

return 0;
}

-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {

if (component == 0) {
return self.leftComponentItems[row];
}

if (component == 1) {
if (self.selectedLeftRow == 0) {
return self.rightComponentItemsA[row];
} else {
return self.rightComponentItemsB[row];
}
}

return @"default";

}

-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
if (component == 0) {
self.selectedLeftRow = row; // We keep track of the selected row
[pickerView reloadComponent:1]; // When we select a row in the left component, update the data on the right component
}
}

@end

Feel free to ask if you don't understand something.

Swift UIPickerView 1st component changes 2nd components data

You need to reorganize a bit to make this work better and to have easier code.

The following would be one solution:

let categories = ["Attractions & Entertainment", "Eating & Drinking", "Education", "Emergency", "Financial Institution", "Lodging Establishment", "Medical & Health", "Place of Worship", "Professional Service", "Public Services & Buildings", "Service", "Stores & Shopping", "Transportation"]
let attrationsAndEntertainment = ["Amusement Center", "Amusement Park", "Art Gallery", "Art Museum", "Bowling Alley", "Community Center", "Event Venue", "Golf Club", "Golf Course", "Live Music Venue", "Movie Theater", "Museum", "National Park", "Night Club", "Park", "Performing Arts Theater", "Stadium", "Theme Park", "Tourist Attraction", "Water Park", "Winery", "Zoo", "Cinema", "Park And Garden"]
let eatingAndDrinking = ["American Restaurant", "Asian Restaurant", "Bakery", "Bar", "Bar & Grill", "Barbecue Restaurant", "Breakfast Restaurant", "Buffet Restaurant", "Café", "Chicken Restaurant", "Coffee Shop", "Deli", "Diner", "Family Restaurant", "Fast Food Restaurant", "French Restaurant", "Hamburger Restaurant", "Ice Cream Shop", "Indian Restaurant", "Italian Restaurant", "Japanese Restaurant", "Korean Restaurant", "Meal Takeaway", "Mexican Restaurant", "Pizza Delivery", "Pizza Restaurant", "Pub", "Ramen Restaurant", "Restaurant", "Sandwich Shop", "Seafood Restaurant", "Sports Bar", "Steak House", "Sushi Restaurant", "Tea House", "Thai Restaurant"]
let education = ["College", "Community College", "Elementary School","Middle School", "High School", "Kindergarten", "Preschool","Primary School", "Private School", "Public School", "Public University", "School", "Tutoring Service", "University"]
let emergency = ["Fire Station", "Police Department", "Police Station"]
let financialInstitution = ["ATM", "Accountant", "Bank", "Credit Union", "Financial Consultant", "Financial Planner", "Insurance Agency","Loan Agency", "Money Transfer Service", "Savings Bank", "Tax Consultant", "Tax Preparation Service"]
let lodgingEstablishment = ["Beach Resort", "Bed & Breakfast", "Budget Hotel", "Campground", "Extended Hotel Stay", "Guest House", "Hostel", "Hotel", "Luxury Hotel", "Motel", "RV Park", "Resort"]
let medicalAndHealth = ["Animal Hospital", "Chiropractor", "Dental Clinic", "Dentist", "Dermatologist", "Doctor", "Eye Care Center", "Family Practice Physician", "General Practitioner", "Home Health Care Services", "Hospital", "Internist", "Medical Center", "Medical Clinic", "Medical Laboratory", "Nursing Agency", "Obstetrician - Gynecologist", "Optometrist", "Pediatrician", "Physical Therapist", "Psychologist", "Veterinarian"]
let placeOfWorship = ["Ashram", "Bahai House of Worship", "Baptist Church", "Buddhist Temple", "Catholic Church", "Church", "Convent", "Gurudwara", "Hindu Temple", "Jain Temple", "Mission", "Monastery", "Mosque", "Pagoda", "Pilgrimage Place", "Place Of Worship", "Religious Destination", "Shinto Shrine", "Synagogue"]
let professionalService = ["Air Conditioning Contractor", "Architect", "Business Management Consultant", "Computer Consultant", "Consultant", "Contractor", "Engineer", "Engineering Consultant", "Internet Marketing Service", "Landscaper", "Lawyer", "Legal Services", "Notary Public", "Software Company", "Website Designer"]
let publicServicesAndBuildings = ["Apartment Building", "Apartment Complex", "Cemetery", "City Government Office", "City or Town Hall", "Condominium Complex", "County Government Office", "Department of Motor Vehicles", "Electric Utility Company", "Government Office", "Idustrial Area", "Library", "Local Government Office", "Public Library"]
let service = ["Advertising Agency", "Auto Body Shop", "Auto Repair Shop", "Barber Shop", "Beauty Salon", "Cabinet Maker", "Cable Company", "Car Repair and Maintenance", "Car Wash", "Caterer", "Cleaning Service", "Commerical Printer", "Computer Repair Service", "Construction Company", "Courier Service", "Dance School", "Day Care Center", "Dry Cleaner", "Electrician", "Employement Agency", "Event Planner", "Freight Forwarding Service", "Funeral Home", "General Contractor", "Gym", "Hair Salon", "Health Club", "Home Builder", "House Cleaning Service", "Interior Designer", "Internet Service Provider", "Laundry Service", "Marketing Agency", "Massage Therapist", "Movie Rental Kiosk", "Nail Salon", "Newspaper Publisher", "Painter", "Pest Control Service", "Photographer", "Plumber", "Post Office", "Property Management Company", "Public Swimming Pool", "Publisher", "Real Estate Agency", "Real Estate Agents", "Real Estate Developer", "Roofing Contractor", "Shipping Company", "Shipping and Mailing Service", "Spa", "Tailor", "Telecommunications Service Provider", "Tire Shop", "Tourist Information Center", "Travel Agency", "Trucking Company"]
let storesAndShopping = ["Appliance Store", "Auto Parts Store", "Baby Store", "Beauty Supply Store", "Bicycle Store", "Book Store", "Boutique", "Bridal Shop", "Building Materials Store", "Butcher Shop", "Car Dealer", "Cell Phone Store", "Childrens Clothing Store", "Clothing Store", "Coffee Store", "Computer Store", "Convenience Store", "Cosmetics Store", "Craft Store", "Department Store", "Dessert Shop", "Discount Store", "Discount Supermarket", "Donut Shop", "Drug Store", "Electrical Supply Store", "Electronics Store", "Fabric Store", "Fashion Accessories Store", "Florist", "Furniture Store", "General Store", "Gift Shop", "Grocery Store", "Hardware Store", "Health Food Store", "Home Goods Store", "Home Improvement Store", "Jeweler", "Jewelry Store", "Lingerie Store", "Liquor Store", "Lottery Retailer", "Market", "Men's Clothing Store", "Motorcycle Dealer", "Office Supply Store", "Optician", "Outdoor Sports Store", "Outlet Mall", "Paint Store", "Pawn Shop", "Pet Store", "Pet Supply Store", "Pharmacy", "Print Shop", "Shoe Store", "Shopping Mall", "Sporting Goods Store", "Sportswear Store", "Stationery Store", "Store", "Supermarket", "Tattoo Shop", "Toy Store", "User Car Dealer", "Video Game Store", "Warehouse Club", "Wine Store", "Women's Clothing Store"]
let transportation = ["Car Rental Agency", "Driving School", "Gas Station", "Parking Garage", "Parking Lot", "Taxi Service", "Transportation Service", "Truck Rental Agency"]

var secondColumnData = [[String]]()

override func viewDidLoad() {
super.viewDidLoad()

secondColumnData = [attrationsAndEntertainment, eatingAndDrinking, education, emergency, financialInstitution, lodgingEstablishment, medicalAndHealth, placeOfWorship, professionalService, publicServicesAndBuildings, service, storesAndShopping, transportation]

pickerView.delegate = self
pickerView.dataSource = self
pickerView.reloadAllComponents()
pickerView.selectRow(0, inComponent: 0, animated: false)
}

func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 2
}

func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if component == 0 {
return categories.count
} else {
let selected = pickerView.selectedRow(inComponent: 0)

return secondColumnData[selected].count
}
}

func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if component == 0 {
return categories[row]
} else {
let selected = pickerView.selectedRow(inComponent: 0)

return secondColumnData[selected][row]
}
}

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if component == 0 {
pickerView.reloadComponent(1)
} else {
let selected = pickerView.selectedRow(inComponent: 0)

someTextField.text = secondColumnData[selected][row]
}
}

An even better solution is to take all of that data out of your code and put it all in a plist file in your app's bundle. Make the plist an array of dictionary. Each dictionary would have a category title (which will be shown in the 1st component of the picker), and the array of values for that category (shown in the 2nd component).

The code to support this data structure would be similar to the code above.

UIPickerView where selected 1st component decides contents of 2nd component is out of sync

I solved the error, however I do not understand why this solves it.

The solution is to imlement the func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)method, which I did not believe to be necessary just to show the fields.

In other words, just add this to my existing code:

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if component == 0 {
pickerView.reloadComponent(1)
} else {
let selectedRowInFirstComponent = pickerView.selectedRow(inComponent: 0)

print(pickerData[selectedRowInFirstComponent].1[row])
}
}

Dynamic PickerView with multiple components: Index out of range

When you call reloadAllComponents() in your didSelectRow you haven't updated the selected rows yet so it's crashing.

Change the order around and it should be fine.

Reset the value of the 1st component of UIPickerView when component 0 is changed might be of interest here as well.

Note pickerView.reloadAllComponents() isn't strictly necessary, as pointed out in the post above. You could just reload the ones that need to change.

A suggestion as well: Your code would be easier to read/maintain if you used say an enum to organize your components so instead of if component == 0 you could have if componentType == .country (or better yet, a switch), for example.

Show data in UIPickerView second component based on first component selection

your code.. with minor modifications..

didSelectRow

- (void)pickerView:(UIPickerView *)thePickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {

if (component == 0) {
club=[[NSString alloc] initWithFormat:@"%@" , [Nations objectAtIndex:row]];
[pickerView reloadComponent:1];
}

}

after that...

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

if(component ==0)
{
return [Nations count];
}
else {
if ([club isEqualToString:@"Espana"]) {
return [Espana count];
}
if ([club isEqualToString:@"Germany"]) {
return [Germany count];
}
// if...
else {
return [England count];
}
}

return 0;
}

and

- (NSString *)pickerView:(UIPickerView *)thePickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
if(component ==0)
{
return [Nations objectAtIndex:row];
}
else {
if ([club isEqualToString:@"Espana"]) {
return [Espana objectAtIndex:row];
}
if ([club isEqualToString:@"Germany"]) {
return [Germany objectAtIndex:row];
}
//if....
else {
return [England objectAtIndex:row];


}
}

return 0;
}

UPD

in h file I have

@interface ViewController : UIViewController <UIPickerViewDataSource, UIPickerViewDelegate> {

IBOutlet UIPickerView *pickerView;
NSMutableArray *arrayColors;
NSMutableArray *Nations;
NSMutableArray *England;
NSMutableArray *Espana;
NSMutableArray *Germany;
NSString *club;
}

after that.. you must connect de pickerView to yours ViewController (dataSource and delegate)
Sample Image

how to set the data in second component based on first component selection in UIPickerview

just check this method .it will work .

 - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
// NSLog(@"Row %i selected in component %i", row, component);
switch (component) {
case 0:
selectedKey = [notesToDisplayForKey objectAtIndex:row];
[pickerView reloadAllComponents];
return;

case 1:

// selectedScale = [scaleNames objectAtIndex:row];
if([selectedKey isEqualToString:@"UK" ])
{
selectedScale = [UKsize1 objectAtIndex:row];
return;
}
else if([selectedKey isEqualToString:@"US"] )
{
selectedScale = [USsize3 objectAtIndex:row];
return;
}
else
{
selectedScale = [EUsize2 objectAtIndex:row];
return;
}
return;

case 2:
selectedValue = [scaleValue objectAtIndex:row];
return;
default:break;
}
}

UIPickerView with multiple components / 3rd component items based on component 1 and 2 selection

Yes, you can automatically select a row of the picker without touching it with your finger. For example:

[self.pickerView selectRow:0 inComponent:2 animated:YES];

Call this before the view appears on the screen. Probably in viewWillAppear:

Update:

Markus and I checked this out over chat, and I came up with a solution. Basically, any time:

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component

is called, if it is component 0 or 1, we need to reload component 2. We do this (within the didSelectRow method) by saying:

[pickerView reloadComponent:2];

There were a couple other minor things in his code that weren't working correctly, but for the purpose of this stack overflow question, this is all that needs to be explained.



Related Topics



Leave a reply



Submit