Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save zenghaojim33/b526344da875b94ff983237b95b2d7ea to your computer and use it in GitHub Desktop.
Save zenghaojim33/b526344da875b94ff983237b95b2d7ea to your computer and use it in GitHub Desktop.
FourthPickerRow (未完成
//
// Quadruple.swift
// PingBa
//
// Created by Anson on 2018/6/5.
// Copyright © 2018年 Zoeker.Inc. All rights reserved.
//
import Foundation
import Eureka
public struct Tuple4<A: Equatable, B: Equatable, C: Equatable, D:Equatable> {
public let a: A
public let b: B
public let c: C
public let d: D
public init(a: A, b: B, c: C, d:D) {
self.a = a
self.b = b
self.c = c
self.d = d
}
}
extension Tuple4: Equatable {}
public func == <A: Equatable, B: Equatable, C: Equatable, D:Equatable>(lhs: Tuple4<A, B, C, D>, rhs: Tuple4<A, B, C, D>) -> Bool {
return lhs.a == rhs.a && lhs.b == rhs.b && lhs.c == rhs.c && lhs.d == rhs.d
}
open class QuadruplePickerInputCell<A, B, C, D> : _PickerInputCell<Tuple4<A, B, C, D>> where A: Equatable, B: Equatable, C: Equatable, D:Equatable {
private var pickerRow: _QuadruplePickerInputRow<A, B, C, D>! { return row as? _QuadruplePickerInputRow<A, B, C, D> }
public required init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
open override func update() {
super.update()
if let selectedValue = pickerRow.value, let indexA = pickerRow.firstOptions().index(of: selectedValue.a),
let indexB = pickerRow.secondOptions(selectedValue.a).index(of: selectedValue.b),
let indexC = pickerRow.thirdOptions(selectedValue.a, selectedValue.b).index(of: selectedValue.c){
picker.selectRow(indexA, inComponent: 0, animated: true)
picker.selectRow(indexB, inComponent: 1, animated: true)
picker.selectRow(indexC, inComponent: 2, animated: true)
}
}
open override func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 3
}
open override func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if component == 0 {
return pickerRow.firstOptions().count
} else if component == 1 {
return pickerRow.secondOptions(pickerRow.selectedFirst()).count
} else {
return pickerRow.thirdOptions(pickerRow.selectedFirst(), pickerRow.selectedSecond()).count
}
}
open override func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if component == 0 {
return pickerRow.displayValueForFirstRow(pickerRow.firstOptions()[row])
} else if component == 1 {
return pickerRow.displayValueForSecondRow(pickerRow.secondOptions(pickerRow.selectedFirst())[row])
} else {
return pickerRow.displayValueForThirdRow(pickerRow.thirdOptions(pickerRow.selectedFirst(), pickerRow.selectedSecond())[row])
}
}
open override func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if component == 0 {
let a = pickerRow.firstOptions()[row]
if let value = pickerRow.value {
guard value.a != a else {
return
}
let b: B = pickerRow.secondOptions(a).contains(value.b) ? value.b : pickerRow.secondOptions(a)[0]
let c: C = pickerRow.thirdOptions(a, b).contains(value.c) ? value.c : pickerRow.thirdOptions(a, b)[0]
let d: D = pickerRow.forthOptions(a, b, c).contains(value.d) ? value.d : pickerRow.forthOptions(a, b, c)[0]
pickerView.reloadComponent(1)
pickerView.reloadComponent(2)
pickerRow.value = Tuple4(a: a, b: b, c: c, d:d)
if b != value.b {
pickerView.selectRow(0, inComponent: 1, animated: true)
}
if c != value.c {
pickerView.selectRow(0, inComponent: 2, animated: true)
}
} else {
let b = pickerRow.secondOptions(a)[0]
let c = pickerRow.thirdOptions(a,b)[0]
pickerRow.value = Tuple4(a: a, b: b, c: pickerRow.thirdOptions(a, b)[0],d:pickerRow.forthOptions(a, b,c)[0])
pickerView.reloadComponent(1)
pickerView.reloadComponent(2)
pickerView.selectRow(0, inComponent: 1, animated: true)
pickerView.selectRow(0, inComponent: 2, animated: true)
}
} else if component == 1 {
let a = pickerRow.selectedFirst()
let b = pickerRow.secondOptions(a)[row]
if let value = pickerRow.value {
guard value.b != b else {
return
}
if pickerRow.thirdOptions(a, b).contains(value.c) {
pickerRow.value = Tuple4(a: a, b: b, c: value.c, d: <#D#>)
pickerView.reloadComponent(2)
update()
return
} else {
pickerRow.value = Tuple4(a: a, b: b, c: pickerRow.thirdOptions(a, b)[0])
}
} else {
pickerRow.value = Tuple4(a: a, b: b, c: pickerRow.thirdOptions(a, b)[0])
}
pickerView.reloadComponent(2)
pickerView.selectRow(0, inComponent: 2, animated: true)
} else {
let a = pickerRow.selectedFirst()
let b = pickerRow.selectedSecond()
pickerRow.value = Tuple4(a: a, b: b, c: pickerRow.thirdOptions(a, b)[row])
}
update()
}
}
open class _QuadruplePickerInputRow<A: Equatable, B: Equatable, C: Equatable, D:Equatable> : Row<QuadruplePickerInputCell<A, B, C, D>>, NoValueDisplayTextConformance {
open var noValueDisplayText: String? = nil
/// Options for first component. Will be called often so should be O(1)
public var firstOptions: (() -> [A]) = {[]}
/// Options for second component given the selected value from the first component. Will be called often so should be O(1)
public var secondOptions: ((A) -> [B]) = {_ in []}
/// Options for third component given the selected value from the first and second components. Will be called often so should be O(1)
public var thirdOptions: ((A, B) -> [C]) = {_, _ in []}
public var forthOptions:((A, B, C) -> [D]) = {_,_,_ in []}
/// Modify the displayed values for the first picker row.
public var displayValueForFirstRow: ((A) -> (String)) = { a in return String(describing: a) }
/// Modify the displayed values for the second picker row.
public var displayValueForSecondRow: ((B) -> (String)) = { b in return String(describing: b) }
/// Modify the displayed values for the third picker row.
public var displayValueForThirdRow: ((C) -> (String)) = { c in return String(describing: c) }
required public init(tag: String?) {
super.init(tag: tag)
}
func selectedFirst() -> A {
return value?.a ?? firstOptions()[0]
}
func selectedSecond() -> B {
return value?.b ?? secondOptions(selectedFirst())[0]
}
}
/// A generic row where the user can pick an option from a picker view displayed in the keyboard area
public final class QuadruplePickerInputRow<A, B, C, D>: _QuadruplePickerInputRow<A, B, C, D>, RowType where A: Equatable, B: Equatable, C: Equatable, D:Equatable{
required public init(tag: String?) {
super.init(tag: tag)
self.displayValueFor = { [weak self] tuple in
guard let tuple = tuple else {
return self?.noValueDisplayText
}
return String(describing: tuple.a) + ", " + String(describing: tuple.b) + ", " + String(describing: tuple.c)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment