在处理具有委托人和数据源的多个控件时,应考虑通过为多个选择器的委托创建单独的对象来避免视图控制器膨胀(即,按照单一职责原则的精神)。这使得这个逻辑出视图控制器本身,并避免了单一繁琐
UIPickerViewDataSource和
UIPickerViewDelegate努力服务的多个采摘与毛茸茸的方法
if-
else或
switch语句。
例如,这是一个视图控制器,它具有两个拾取器的出口,但是您不必为视图控制器添加代码来管理
dataSource和
delegate为这些拾取器而烦恼,您可以为每个拾取器拥有单独的对象,并且所有视图控制器要做的就是说哪个委托对象将处理哪个选择器:
class ViewController: UIViewController { @IBOutlet weak var namePicker: UIPickerView! @IBOutlet weak var numberPicker: UIPickerView! let namePickerDelegate = NamePickerDelegate() let numberPickerDelegate = NumberPickerDelegate() override func viewDidLoad() { super.viewDidLoad() namePicker.delegate = namePickerDelegate namePicker.dataSource = namePickerDelegate numberPicker.delegate = numberPickerDelegate numberPicker.dataSource = numberPickerDelegate } @IBAction func didTapButton(_ sender: Any) { let namevalue = namePicker.selectedRow(inComponent: 0) let numberValue = numberPicker.selectedRow(inComponent: 0) print("(namevalue); (numberValue)") }}唯一的技巧是确保对这些委托对象保持强烈的引用,如上所示,因为按照最佳做法,选择器本身对引用的委托仅具有较弱的引用。
Picker委托方法的实现更加简洁:
class NamePickerDelegate: NSObject, UIPickerViewDataSource, UIPickerViewDelegate { let names = ["Mo", "Larry", "Curley"] func numberOfComponents(in pickerView: UIPickerView) -> Int { return 1 } func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { return names.count } func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { return names[row] }}class NumberPickerDelegate: NSObject, UIPickerViewDataSource, UIPickerViewDelegate { let numbers: [String] = { let formatter = NumberFormatter() formatter.numberStyle = .spellOut return (0 ..< 100).compactMap { formatter.string(for: $0) } // use `flatMap` in Xpre versions prior to 9.3 }() func numberOfComponents(in pickerView: UIPickerView) -> Int { return 1 } func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { return numbers.count } func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { return numbers[row] }}现在,显然,这仍然是一个简化的示例,但是美丽之处在于,随着代码变得越来越复杂,详细信息被封装在单独的对象中,而不是将所有代码都包含在单个视图控制器中。
如果需要,可以让视图控制器为委托/数据源对象提供字符串列表。实际上,这简化了它,因为对于选择器委托只需要一个类,而对于每个选择器只需实例化一个不同的类:
class ViewController: UIViewController { let names = ["Mo", "Larry", "Curley"] let numbers: [String] = { let formatter = NumberFormatter() formatter.numberStyle = .spellOut return (0 ..< 100).compactMap { formatter.string(for: $0) } // use `flatMap` in Xpre versions prior to 9.3 }() @IBOutlet weak var numberPickerOne: UIPickerView! @IBOutlet weak var numberPickerTwo: UIPickerView! @IBOutlet weak var namePicker: UIPickerView! lazy var numberPickerOneDelegate: PickerDelegate = PickerDelegate(strings: self.numbers) lazy var numberPickerTwoDelegate: PickerDelegate = PickerDelegate(strings: self.numbers) lazy var namePickerDelegate:PickerDelegate = PickerDelegate(strings: self.names) override func viewDidLoad() { super.viewDidLoad() numberPickerOne.delegate = numberPickeroneDelegate numberPickerOne.dataSource = numberPickeroneDelegate numberPickerTwo.delegate = numberPickerTwoDelegate numberPickerTwo.dataSource = numberPickerTwoDelegate namePicker.delegate = namePickerDelegate namePicker.dataSource = namePickerDelegate }}class PickerDelegate: NSObject, UIPickerViewDataSource, UIPickerViewDelegate { let strings: [String] init(strings: [String]) { self.strings = strings super.init() } func numberOfComponents(in pickerView: UIPickerView) -> Int { return 1 } func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { return strings.count } func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { return strings[row] }}


