如何在 ViewController 之外符合 UIPickerViewDelegate 和 UIPickerViewDataSource?
How conform to UIPickerViewDelegate and UIPickerViewDataSource outside of a ViewController?
我想在一个场景中拥有多个 UIPickerView,而不会使我的视图控制器因委托函数而膨胀。我在 UIPickerViews 上看到的所有教程都建议使用视图控制器本身作为 UIPickerView
.
的委托
如何将此委托代码移出 ViewController
?
受到 this tutorial 的启发,这里是一个视图控制器,它将自己指定为它的 UIPickerViews 的委托。我批评用于将行为映射到每个 UIPickerView
:
的 if/else 逻辑
import UIKit
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
@IBOutlet weak var pickerViewA: UIPickerView!
@IBOutlet weak var pickerViewB: UIPickerView!
let contentsA = ["1A", "2A", "3A"]
let contentsB = ["1B", "2B", "3B", "4B"]
override func viewDidLoad() {
super.viewDidLoad()
pickerViewA.delegate = self
pickerViewA.dataSource = self
pickerViewB.delegate = self
pickerViewB.dataSource = self
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1 //Applies to both pickerViewA & pickerViewB
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView == pickerViewA {
return contentsA.count
} else {
return contentsB.count
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView == pickerViewA {
return contentsA[row]
} else {
return contentsB[row]
}
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if pickerView == pickerViewA {
// Do something A
} else {
// Do something B
}
}
}
理想情况下,我希望有一个符合这些协议的自定义 class,然后为每个 UIPickerView
创建此 class 的新实例,以便它们具有唯一性委托和行为。
当我尝试定义一个名为 'PickerDelegate' 的单独 class 并符合 UIPickerViewDelegate
和 UIPickerViewDataSource
时,我在 Xcode 中收到此错误:
Type 'PickerDelegate' does not conform to protocol 'NSObjectProtocol'
显然 UIPickerViewDelegate
& UIPickerViewDataSource
继承自 NSObjectProtocol
。如果我添加协议存根(如 Xcode 所建议的),我会得到一长串我不热衷于实现的功能。
是否有更简单的方法在视图控制器之外遵守这些协议?
When I attempt to define a separate class called 'PickerDelegate' that conforms to UIPickerViewDelegate & UIPickerViewDataSource, I get this error in Xcode:
只需让您的 PickerDelegate 成为 NSObject 的子类即可。
class PickerDelegate : NSObject, UIPickerViewDelegate, UIPickerViewDataSource {
这不是强加,而是必要的,因为 Cocoa 是 Objective-C,否则甚至无法看到您的委托和数据源方法。
你可以像这样添加扩展,在任何你想使用 UIpiker 的 UIviewController 中,只需在视图 didload() 中设置委托
extension UIViewController: UIPickerViewDelegate, UIPickerViewDataSource {
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView == pickerViewA {
return contentsA.count
} else {
return contentsB.count
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView == pickerViewA {
return contentsA[row]
} else {
return contentsB[row]
}
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if pickerView == pickerViewA {
// Do something A
} else {
// Do something B
}
}
}
我想在一个场景中拥有多个 UIPickerView,而不会使我的视图控制器因委托函数而膨胀。我在 UIPickerViews 上看到的所有教程都建议使用视图控制器本身作为 UIPickerView
.
如何将此委托代码移出 ViewController
?
受到 this tutorial 的启发,这里是一个视图控制器,它将自己指定为它的 UIPickerViews 的委托。我批评用于将行为映射到每个 UIPickerView
:
import UIKit
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
@IBOutlet weak var pickerViewA: UIPickerView!
@IBOutlet weak var pickerViewB: UIPickerView!
let contentsA = ["1A", "2A", "3A"]
let contentsB = ["1B", "2B", "3B", "4B"]
override func viewDidLoad() {
super.viewDidLoad()
pickerViewA.delegate = self
pickerViewA.dataSource = self
pickerViewB.delegate = self
pickerViewB.dataSource = self
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1 //Applies to both pickerViewA & pickerViewB
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView == pickerViewA {
return contentsA.count
} else {
return contentsB.count
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView == pickerViewA {
return contentsA[row]
} else {
return contentsB[row]
}
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if pickerView == pickerViewA {
// Do something A
} else {
// Do something B
}
}
}
理想情况下,我希望有一个符合这些协议的自定义 class,然后为每个 UIPickerView
创建此 class 的新实例,以便它们具有唯一性委托和行为。
当我尝试定义一个名为 'PickerDelegate' 的单独 class 并符合 UIPickerViewDelegate
和 UIPickerViewDataSource
时,我在 Xcode 中收到此错误:
Type 'PickerDelegate' does not conform to protocol 'NSObjectProtocol'
显然 UIPickerViewDelegate
& UIPickerViewDataSource
继承自 NSObjectProtocol
。如果我添加协议存根(如 Xcode 所建议的),我会得到一长串我不热衷于实现的功能。
是否有更简单的方法在视图控制器之外遵守这些协议?
When I attempt to define a separate class called 'PickerDelegate' that conforms to UIPickerViewDelegate & UIPickerViewDataSource, I get this error in Xcode:
只需让您的 PickerDelegate 成为 NSObject 的子类即可。
class PickerDelegate : NSObject, UIPickerViewDelegate, UIPickerViewDataSource {
这不是强加,而是必要的,因为 Cocoa 是 Objective-C,否则甚至无法看到您的委托和数据源方法。
你可以像这样添加扩展,在任何你想使用 UIpiker 的 UIviewController 中,只需在视图 didload() 中设置委托
extension UIViewController: UIPickerViewDelegate, UIPickerViewDataSource {
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView == pickerViewA {
return contentsA.count
} else {
return contentsB.count
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView == pickerViewA {
return contentsA[row]
} else {
return contentsB[row]
}
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if pickerView == pickerViewA {
// Do something A
} else {
// Do something B
}
}
}