可以制作通用枚举UIPickerView

时间:2017-08-15 20:42:09

标签: swift generics uipickerview

是否可以编写一个通用的UIPickerView子类,您可以在其中传入任意枚举类型,并使用所有枚举的情况填充选择器视图?

注意:这通常需要在枚举类型中任意传递。

2 个答案:

答案 0 :(得分:1)

所以我终于能够编写一个通用的枚举感知选择器视图了。这就是我做的。首先,我做了一个PickableEnum协议,如下:

protocol PickableEnum: Hashable {
   static var allValues: [Self] {get}
   var pickerText:   String {get}
}

我需要能够一般地知道所有枚举案例是什么。这是allValues属性的工作,我在网上找到了它的实现。

https://theswiftdev.com/2017/01/05/18-swift-gist-generic-allvalues-for-enums/

以下是代码:

extension PickableEnum {

   static func cases() -> AnySequence<Self> {
      typealias S = Self
      return AnySequence { () -> AnyIterator<S> in
         var raw = 0
         return AnyIterator {
            let current : Self = withUnsafePointer(to: &raw) { $0.withMemoryRebound(to: S.self, capacity: 1) { $0.pointee } }
            guard current.hashValue == raw else { return nil }
            raw += 1
            return current
         }
      }
   }

   static var allValues: [Self] {
      return Array(self.cases())
   }
}

PickableEnum还有一个名为pickerText的只读字符串属性,用于获取将出现在选择器界面中的文本。

其余的都是微不足道的。使您的UI类采用适当类型的通用限定符,然后相应地配置UIPickerView:

class EnumPickerView<T:PickableEnum> : UIPickerView, UIPickerViewDelegate, UIPickerViewDataSource {

   private let enumCases = T.allValues
   private var currentValue: T

   init(frame: CGRect, initialValue: T) {
      currentValue = initialValue
      super.init(frame: frame)
      dataSource = self
      delegate = self
   }

   required init?(coder aDecoder: NSCoder) {
      fatalError("init(coder:) has not been implemented")
   }

   var value: T {
      get {
         return currentValue
      }
   }

   func numberOfComponents(in pickerView: UIPickerView) -> Int {
      return 1
   }

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

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

   func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
      currentValue = enumCases[row]
   }
}

答案 1 :(得分:-1)

试试这个:

enum SomeValues: Int {

    static var count: Int { return SomeValues.lastValue.hashValue + 1 }

    case valueA = 0
    case valueB = 1
    case valueC = 2
    case lastValue = 3
    case noValue = 4

    func rawString() -> String {
        return String(describing: self)
    }
}

使用选择器的值:

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

func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
    return SomeValues.count
}

// MARK: - UIPickerViewDelegate

func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {

    guard let value = SomeValues(rawValue: component), value != .noValue else { return "Handle however you want" }

    return value.rawString()
}