iOS / Swift —创建多个动态选择器视图:快速教程

我一直在为我在Facebook上的项目完成最后的接触而努力,您可以在这里了解更多信息。 在我为应用程序püler贡献的所有功能中,我最喜欢的功能之一是汽车选择器视图:

为了实现这一点,了解UIPickerView对象和选择器视图与您拥有的数据进行交互的方式非常重要。 就我而言,我的数据结构如下所示:

{make1:{model1:{year1,year2,…},model2:{year1,year2,…},…},make2:{…},…}

所以基本上是字典的字典,是的,我知道您现在可能已经讨厌我了,但请听我说。 由于汽车的工作结构,这是必要的,对于仍然不了解正在发生的事情的你们来说,看起来像这样。

(请原谅丑陋的图画^)。 无论如何,在宏伟的计划中,有多个品牌,每个品牌都有多个型号,每个型号都有几年。 现在,为了制作动态选择器视图,我们首先在情节提要中添加三个UIPickerViews并为其创建出口。 相应地命名,我的被称为:

之后,我们需要设置PickerViewDelegate,以便Xcode知道我们将为pickerView提供数据/指令,而不是它。 为此,请确保在类标题中添加UIPickerViewDataSourceUIPickerViewDelegate 。 在将这两个函数相加后,您应该得到错误消息,表明您尚未声明某些函数,但不要担心,我们马上就可以解决这些问题!

我们现在必须实现的三个功能是:

  func numberOfComponentsInPickerView(pickerView:UIPickerView)-> Int 
  func pickerView(pickerView:UIPickerView,numberOfRowsInComponent组件:Int)-> Int 
  func pickerView(pickerView:UIPickerView,titleForRow行:Int,forComponent组件:Int)->字符串? 

第一个询问在pickerView中应包含多少个组件。 我选择有1,但是具有多个组件的pickerView看起来像这样:

我选择不使用它的原因是一个简单的设计决定,但是我的代码也可以进行编辑以适合这样的内容(也许会在将来发表文章?)。

因为我决定每个pickerView仅保留一个组件(并且在一个pickerView中不包含3个组件),所以我在函数中简单地返回了1:

  func numberOfComponentsInPickerView(pickerView:UIPickerView)-> Int { 
 返回1 
  } 

现在来看两个稍微复杂的功能。 让我们开始

  func pickerView(pickerView:UIPickerView,numberOfRowsInComponent组件:Int)-> Int 

该函数要求每个组件中需要的行数,但是由于每个pickerViews只有一个组件,因此我们可以为每个组件返回一个特定的整数。 我们要返回makePicker的品牌数量, modelPicker的模型数量以及yearPicker的年数。 如果我们拥有所有品牌,型号和年份的阵列 ,那么我们要做的就是:

  func pickerView(pickerView:UIPickerView,numberOfRowsInComponent组件:Int)-> Int { 
 如果pickerView == makePicker { 
 返回listOfMakes.count 
  } 
 否则,如果pickerView == modelPicker { 
 返回listOfModels.count 
  } 
 其他{ 
 返回listOfYears.count 
  } 
  } 

不幸的是,我们没有listOfMakes,listOfModels或listOfYears,因为listOfModels取决于所选的品牌listOfYears取决于所选的模型。 要获得listOfMakes,我们只需从字典中获取所有make即可(确保makeList在类中声明为类变量:

 让listOfMakes:[String] = [String]() 
让listOfModels:[String] = [String]()
让listOfYears:[String = [String]()
var carlist:字典<String,Dictionary <String,Dictionary >> = Dictionary()
  //假设您已经填充了此数据结构。 
//最里面的字典保存{year:id},并且需要// mpg。 没有Id,结构可能类似于// this:字典<String,Dictionary <String,Dictionary >>>>
 覆盖func viewDidLoad(){ 
listOfMakes = Array(carDictionary.keys)
}

然后,当用户第一次查看PickerViews时,我们只希望第一个make的模型出现在我们的makeViewController中。 因此,在我的视图中确实加载了以下代码:

 覆盖func viewDidLoad(){ 
listOfMakes = Array(carDictionary.keys)
listOfModels =(CarList.getAllModels(self.carlist,make:self.listOfMakes [0]))。sort()
让firstCar = listOfMakes [0]
 让modelsDictionary = carDictionary [firstCar]! 作为Dictionary <String,Dictionary > 
 让listOfModels = Array(modelsDictionary.keys) 
  } 

然后对listOfYears进行相同的操作,因为我们需要只显示第一个模型包含的多个模型中第一个模型的年份。

 覆盖func viewDidLoad(){ 
self.listOfMakes = Array(carDictionary.keys)
让firstCar = listOfMakes [0]
 让modelsDictionary = carList [firstCar]! 作为Dictionary <String,Dictionary > 
  self.listOfModels = Array(modelsDictionary.keys).sort() 
让firstModel = listOfModels [0]
 让yearsDictionary = modelsDictionary [firstModel]! 作为Dictionary  
self.listOfYears = Array(yearsDictionary.keys).sort()

  } 

我再次假设您已经填充了“树状”数据结构。

现在我们已经设置了列表,我们的numberOfRowsInComponent函数应该已经完成​​。

最后,要使用数据填充pickerView,我们使用相同的三个数组,并简单地放置:

  func pickerView(pickerView:UIPickerView,titleForRow行:Int,forComponent组件:Int)->字符串?  { 
 如果pickerView == makePicker { 
 返回listOfMakes [行] 
  } 
 否则,如果pickerView == modelPicker { 
 返回listOfModels [行] 
  } 
 其他{ 
 返回listOfYears [row] 
  } 
  } 

该pickerView最重要的部分是每次您更改PickerViews之一时,它都需要响应。 现在,我们已经为委托提供了两个必需的功能,我们必须再实现一个附加功能,以便添加动态特性。

  func pickerView(pickerView:UIPickerView,didSelectRow行:Int,inComponent组件:Int){} 

在开始填写函数之前,我们需要在类变量中添加以下内容:

  var makeRow = 0 
  var modelRow = 0 
  var yearRow = 0 

现在我们可以跟踪每个选择器在哪一行,因此可以动态更改其他两个(如果需要)。

我们首先添加以下帮助程序功能,这些功能与我们在viewDidLoad中所做的非常相似。

  setModelsList(make:String){ 
 让modelsDictionary = carList [make]! 作为Dictionary <String,Dictionary > 
  self.listOfModels = Array(modelsDictionary.keys).sort() 
  } 
  setYearsList(make:String,model:String){ 
让modelsDictionary = carList [make]! 作为Dictionary <String,Dictionary >
 让modelsList = Array(modelsDictionary.keys) 
让yearsDictionary = modelsDictionary [model]! 作为Dictionary
self.listOfYears = Array(yearsDictionary.keys).sort()
  } 

这些帮助器功能使我们可以轻松地将模型设置为年份列表,具体取决于选择了哪个品牌(品牌列表)以及选择哪个品牌型号(年份列表)。

现在,对于实际的魔术:

  func pickerView(pickerView:UIPickerView,didSelectRow行:Int,inComponent组件:Int){ 
 如果pickerView == makePicker { 
  makeRow =行 
  setModelsList(listOfMakes [makeRow]) 
  setYearsList(listOfMakes [makeRow],模型:listOfModels [0]) 
  modelPicker.selectRow(0,inComponent:0,动画:true) 
  yearPicker.selectRow(0,inComponent:0,动画:true) 
  self.modelPicker.reloadAllComponents() 
  self.yearPicker.reloadAllComponents() 
  } 
 否则,如果pickerView == modelPicker { 
  modelRow =行 
  setYearsList(listOfMakes [makeRow],模型:listOfModels [modelRow]) 
  yearPicker.selectRow(0,inComponent:0,动画:true) 
  self.modelPicker.reloadAllComponents() 
  self.yearPicker.reloadAllComponents() 
  } 
 其他{ 
  //选择特定年份后,就可以做任何您想做的事情。 
  } 
  } 

此时,pickerView应该响应品牌或模型选择器中的任何更改。 的

一些注意事项:

  yearPicker.selectRow(0,inComponent:0,动画:true) 

该语句将viewPicker向上滚动到顶部(或索引0,这是第一个参数代表的内容)。

2。

  reloadAllComponents() 

每当您更改每个选择器视图的数据时,都应调用此功能。 在这种情况下,我们更改了模型和年份列表中的数据,因此必须重新加载每个以显示新值。

可以实现的其他功能包括:显示当前选择的汽车,用按钮添加当前汽车等。有关实现或gif功能的任何问题都可以重定向到sumedha.mehta@gmail.com。