5

I created this UIPickerView where the 1 components selection decides what the 2 components data is. Yet, whenever I start moving the UIPicker it throws the "libc++abi.dylib: terminating with uncaught exception of type NSException" error with Thread 1. I am guessing the data is the problem?? Not Sure

var wheelPickerContents: [[String]] = []

var 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"]
var 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"]
var 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"]
var education = ["College", "Community College", "Elementary School","Middle School", "High School", "Kindergarten", "Preschool","Primary School", "Private School", "Public School", "Public University", "School", "Tutoring Service", "University"]
var emergency = ["Fire Station", "Police Department", "Police Station"]
var financialInstitution = ["ATM", "Accountant", "Bank", "Credit Union", "Financial Consultant", "Financial Planner", "Insurance Agency","Loan Agency", "Money Transfer Service", "Savings Bank", "Tax Consultant", "Tax Preparation Service"]
var lodgingEstablishment = ["Beach Resort", "Bed & Breakfast", "Budget Hotel", "Campground", "Extended Hotel Stay", "Guest House", "Hostel", "Hotel", "Luxury Hotel", "Motel", "RV Park", "Resort"]
var 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"]
var 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"]
var 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"]
var 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"]
var 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"]
var 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"]
var transportation = ["Car Rental Agency", "Driving School", "Gas Station", "Parking Garage", "Parking Lot", "Taxi Service", "Transportation Service", "Truck Rental Agency"]


override func viewDidLoad() {
    super.viewDidLoad()

 pickerView.delegate = self
 pickerView.dataSource = self
 pickerView.reloadAllComponents()

 wheelPickerContents = [categories, attrationsAndEntertainment]

}

func numberOfComponents(in pickerView: UIPickerView) -> Int {
    return wheelPickerContents.count
}

func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
    return wheelPickerContents[component].count
}

func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
    return wheelPickerContents[component][row]
}

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
    let whatConversion = wheelPickerContents[0][pickerView.selectedRow(inComponent: 0)]

    switch(whatConversion) {
        case "Attractions & Entertainment":
        wheelPickerContents = [categories, attrationsAndEntertainment]
        pickerView.numberOfRows(inComponent: wheelPickerContents.count)

        break

        case "Eating & Drinking":
        wheelPickerContents = [categories, eatingAndDrinking]
        pickerView.numberOfRows(inComponent: wheelPickerContents.count)

        break

        case "Education":
        wheelPickerContents = [categories, education]
        pickerView.numberOfRows(inComponent: wheelPickerContents.count)

        break

        case "Emergency":
        wheelPickerContents = [categories, emergency]
        pickerView.numberOfRows(inComponent: wheelPickerContents.count)

        break

        case "Financial Institution":
        wheelPickerContents = [categories, financialInstitution]
        pickerView.numberOfRows(inComponent: wheelPickerContents.count)

        break

        case "Lodging Establishment":
        wheelPickerContents = [categories, lodgingEstablishment]
        pickerView.numberOfRows(inComponent: wheelPickerContents.count)

        break

        case "Medical & Health":
        wheelPickerContents = [categories, medicalAndHealth]
        pickerView.numberOfRows(inComponent: wheelPickerContents.count)

        break

        case "Place of Worship":
        wheelPickerContents = [categories, placeOfWorship]
        pickerView.numberOfRows(inComponent: wheelPickerContents.count)

        break

        case "Professional Service":
        wheelPickerContents = [categories, professionalService]
        pickerView.numberOfRows(inComponent: wheelPickerContents.count)

        break

        case "Public Services & Buildings":
        wheelPickerContents = [categories, publicServicesAndBuildings]
        pickerView.numberOfRows(inComponent: wheelPickerContents.count)

        break

        case "Service":
        wheelPickerContents = [categories, service]
        pickerView.numberOfRows(inComponent: wheelPickerContents.count)

        break

        case "Stores & Shopping":
        wheelPickerContents = [categories, storesAndShopping]
        pickerView.numberOfRows(inComponent: wheelPickerContents.count)

        break

        case "Transportation":
        wheelPickerContents = [categories, transportation]
        pickerView.numberOfRows(inComponent: wheelPickerContents.count)

        break

    default:
        break
    }
}

Update

This start going crazy. Once I start moving the second component it start changed the 1st component until it throws a "index out of range" on the "businessType.text = secondColumnData[selected][row]" I just tried changing the positions of the business category label but not working

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

        businessType.text = secondColumnData[selected][row]
    }
   businessCategory.text = categories[row]
}

EDIT added text labels

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {

    if component == 0 {
        pickerView.reloadComponent(1)
    } else {
        let selected = pickerView.selectedRow(inComponent: 0)

        businessCategory.text = categories[selected]
        businessType.text = secondColumnData[selected][row]
    }

}
Lukas Bimba
  • 817
  • 14
  • 35

1 Answers1

5

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.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • For "let secondColumnData" I am getting "Cannot use instance member 'attractionsAndEntertainment' within property initializer; property initializers run before 'self' is available". – Lukas Bimba Aug 19 '17 at 00:23
  • 1
    "titleForRow - return secondColumnData[selected][row]" is throwing "fatal error: Index out of range" – Lukas Bimba Aug 19 '17 at 00:30
  • When that happens, what are the values for `selected` and `row`? – rmaddy Aug 19 '17 at 00:33
  • I think the problem is there is no initial selection of component 0. See the last line I just added to `viewDidLoad`. That should fix it. – rmaddy Aug 19 '17 at 00:35
  • I switched your numbers because you switch my rows around, I changed 1 to 0 and 0 to 1, except for the did select row method. I can scroll up and down the 0 row yet 1 does not changed to what was selected and also once I scroll 1 thats when it throws the "fatal error: Index Out Of Range" – Lukas Bimba Aug 19 '17 at 00:40
  • And for the "secondColumnData" you just took all the categories and put it in 1 instead of them being separate as they should be – Lukas Bimba Aug 19 '17 at 00:49
  • rmaddy any solution? – Lukas Bimba Aug 19 '17 at 00:57
  • I did have a typo. All of the `if component == 1` should have been `if component == 0`. Everything else looks right. All the `selectedRow` calls should be `0` as I have it. If you changed those to `1` that will be a problem. And my use of `secondColumnData` is correct. It is supposed to be an array of arrays. – rmaddy Aug 19 '17 at 01:35
  • secondColumnData should have a ":" not a "=" – Lukas Bimba Aug 19 '17 at 01:40
  • by the way how could I attribute my selected secondColumnData to my text field? I just assigned in "DidSelectRow" my text field like "businessCategory.text = categories[row]" but I am having a problem with secondColumnData – Lukas Bimba Aug 19 '17 at 01:49
  • Just update `didSelectRow` with similar logic to `titleForRow` to get the value from `secondColumnData`. – rmaddy Aug 19 '17 at 01:50
  • I keep getting a error Unexpected non-void return value in void function, can you please help with this? – Lukas Bimba Aug 19 '17 at 02:01
  • See my updated `didSelectRow` for a basic idea of what you need. – rmaddy Aug 19 '17 at 02:03
  • Can you take a look at my update please? Once I start scrolling on component 1, component 0 starts changing the displayed text and then component 1's displayed text starts changing. Whats presented in the UIPicker is fine but the displayed text starts going crazy – Lukas Bimba Aug 19 '17 at 02:16
  • Move the line `businessCategory.text = categories[row]` to inside the `if` since you only want to do that if `component == 0`. – rmaddy Aug 19 '17 at 03:33
  • Perfect!! pickerView.reloadComponent(1) is the one I needed! Thks a lot – abanet Nov 30 '18 at 12:04