使用枚举案例作为段控件在 pickerview 中显示数据类型

Using enums case as segment control to show types of data in pickerview

我是 swift 的新手,我正在考虑一种使用段控制理想地填充数据的方法,这是我以前没有尝试过的。

VC 布局如下

期望所选类别类型段控件的结果显示基于 pickerview 类别类型的数据列表

此代码处于试错模式,因为我对如何执行我希望获得的结果没有确切的想法。

 func appendDefaultCategoryTypes() {
        categories = realm.objects(Category.self)
        if categories.count == 0 {
            try! realm.write() {
                let defaultCategories = [
                    Category(type: .Expense, name: "EXPENSE 1"),
                    Category(type: .Expense, name: "EXPENSE 2"),
                    Category(type: .Income, name: "INCOME 1"),
                    Category(type: .Income, name: "INCOME 2"),

                ]
                realm.add(defaultCategories)

            }
        }
    }

//MARK: - Transaction Section
class Transaction : Object {
    //Child of Transaction
    let parentAccount = LinkingObjects(fromType: Account.self, property: "ofTransactions")

    @objc dynamic var categoryType : Category?
    @objc dynamic var amount : String = ""
    @objc dynamic var date : String = ""

}
//MARK: - Transaction Category Section

enum CategoryType : String, CaseIterable {
    case Income = "Income"
    case Expense = "Expense"

    static let allValues = [Income, Expense]

    init?(id : Int) {
        switch id {
        case 1:
            self = .Income
        case 2:
            self = .Expense
      default:
                 return nil
        }
    }

}



class Category : Object {
    @objc dynamic var type : String = CategoryType.Income.rawValue
    @objc dynamic var name : String = ""

    convenience init(type:CategoryType, name: String) {
        self.init()
        self.type = type.rawValue
        self.name = name
    }

}
//VC
    var categories : Results<Category>!

    var picker = UIPickerView()

    @IBAction func categoryTypeSC(_ sender: UISegmentedControl) {
        guard let selectedCategoryType = CategoryType.(rawValue: sender.selectedSegmentIndex) else {
            fatalError("no corresponding category type for the index selected by segment control")
        }
        switch selectedCategoryType {
        case .income :
            print("Income in SC selected")
        case .expense :
            print("Expense in SC selected")
        }

    }

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
//        if categorySCoutlet.selectedSegmentIndex == 0 {
//            return CategoryType.income.count
//        } else if categorySCoutlet.selectedSegmentIndex == 1 {
//            return CategoryType.expense.count
//        }
        return categories.count
    }

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
//        if categorySCoutlet.selectedSegmentIndex == 0 {
//            return
//        } else if categorySCoutlet.selectedSegmentIndex == 1 {
//            return
//        }
//        return "None"
        return categories[row].name
    }

在您的视图控制器中,您需要跟踪与分段控件指示的类型相对应的类别。我称之为 currentCategories.

class ViewController: UIViewController {

    @IBOutlet weak var segmentedControl: UISegmentedControl!
    @IBOutlet weak var textField: UITextField!

    var categories: Results<Category>!
    var currentCategories: Results<Category>!

    lazy var pickerView: UIPickerView = UIPickerView()

    override func viewDidLoad() {
        super.viewDidLoad()

        let realm = try! Realm()
        categories = realm.objects(Category.self)

        appendDefaultCategoryTypes()

        currentCategories = categories.filter("type == %@", CategoryType.income.rawValue)
        textField.text = currentCategories.first?.name

        textField.inputView = pickerView

        pickerView.delegate = self
        pickerView.dataSource = self

        segmentedControl.addTarget(self, action: #selector(onCategoryTypeChanged(_:)), for: .valueChanged)
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)

        if touches.first?.view == view {
            textField.resignFirstResponder()
        }
    }
}

当分段控件值发生变化时,您需要刷新选择器,以便内容反映所选类别类型。

extension ViewController {

    @IBAction func onCategoryTypeChanged(_ sender: UISegmentedControl) {
        guard let type = CategoryType(id: sender.selectedSegmentIndex) else {
            fatalError("no corresponding category type for the index selected by segment control")
        }
        currentCategories = categories.filter("type == %@", type.rawValue)
        textField.text = currentCategories.first?.name
        pickerView.reloadAllComponents()
        pickerView.selectRow(0, inComponent: 0, animated: true)
    }
}

在您的选择器数据源和委托方法中,您需要从反映当前类型的类别中引用数据。

extension ViewController: UIPickerViewDelegate, UIPickerViewDataSource {
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }

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

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

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        textField.text = currentCategories[row].name
    }
}

请注意,我冒昧地更改了您的 CategoryType 枚举中的一些内容。索引应从零开始,大小写应小写。

enum CategoryType : String, CaseIterable {
    case income = "income"
    case expense = "expense"

    init?(id : Int) {
        if id < CategoryType.allCases.count {
            self = CategoryType.allCases[id]
        } else {
            return nil
        }
    }
}