Swift UIPickerView 第一个组件更改第二个组件数据

Posted

技术标签:

【中文标题】Swift UIPickerView 第一个组件更改第二个组件数据【英文标题】:Swift UIPickerView 1st component changes 2nd components data 【发布时间】:2017-08-19 00:04:23 【问题描述】:

我创建了这个 UIPickerView,其中 1 个组件的选择决定了 2 个组件的数据是什么。然而,每当我开始移动 UIPicker 时,它都会在线程 1 中引发“libc++abi.dylib:以 NSException 类型的未捕获异常终止”错误。我猜数据是问题所在??不确定

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
    

更新

这开始变得疯狂。一旦我开始移动第二个组件,它就会开始更改第一个组件,直到它在“businessType.text = secondColumnData[selected][row]”上抛出“index out of range”,我只是尝试更改业务类别标签的位置,但是不工作

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]

编辑添加的文本标签

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]
    


【问题讨论】:

试试picker.reloadComponent(1)而不是pickerView.numberOfRows(inComponent: wheelPickerContents.count) 总的来说,我认为您的实现过于复杂,您只需要一个组件 0 的数组,即类别数组,并根据组件 0 的选择更改组件 1 的数组 似乎我的复杂实现是要走的路 Reinier Melian 想为您的解决方案提供代码? 我认为你已经得到了来自 @rmaddy 的答案,这是这里最好的答案之一,所以如果你的解决方案现在有效,那么祝你好运并快乐编码 【参考方案1】:

您需要重新组织一下以使这项工作更好地工作并编写更简单的代码。

以下是一种解决方案:

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]
    

更好的解决方案是将所有这些数据从您的代码中取出,并将其全部放入应用程序包中的 plist 文件中。使 plist 成为字典数组。每个字典都有一个类别标题(将显示在选择器的第一个组件中),以及该类别的值数组(显示在第二个组件中)。

支持这种数据结构的代码与上面的代码类似。

【讨论】:

对于“let secondColumnData”,我得到“不能在属性初始化程序中使用实例成员 'attractionsAndEntertainment';属性初始化程序在 'self' 可用之前运行”。 “titleForRow - return secondColumnData[selected][row]”正在抛出“致命错误:索引超出范围” 发生这种情况时,selectedrow 的值是多少? 我认为问题是没有初始选择组件 0。请参阅我刚刚添加到 viewDidLoad 的最后一行。那应该可以解决它。 我切换了你的数字,因为你切换了我的行,我将 1 更改为 0 并将 0 更改为 1,除了 did select row 方法。我可以向上和向下滚动 0 行但 1 不会更改为所选内容,并且一旦我滚动 1 就会抛出“致命错误:索引超出范围”

以上是关于Swift UIPickerView 第一个组件更改第二个组件数据的主要内容,如果未能解决你的问题,请参考以下文章

在 Swift 中为选定的 UIPickerView 行设置动画背景颜色

如何在 swift 中为 UIPickerview 的 2 组件数组添加新元素

如何在 UIPickerview iOS swift 中为组件赋予标题

Swift 中的第一个 iOS 应用程序 - UIPickerView 中的问号

致命错误:索引超出范围 / UIPickerView /Array/ Swift

超过 1 个 UIPickerView Swift