使用枚举案例作为段控件在 pickerview 中显示数据类型
Using enums case as segment control to show types of data in pickerview
我是 swift 的新手,我正在考虑一种使用段控制理想地填充数据的方法,这是我以前没有尝试过的。
VC 布局如下
- CategoryType 段控件:控制 CategoryType)
- 具有选择器功能的 CategoryTextField:键盘将显示来自类别的数据列表
期望所选类别类型段控件的结果显示基于 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
}
}
}
我是 swift 的新手,我正在考虑一种使用段控制理想地填充数据的方法,这是我以前没有尝试过的。
VC 布局如下
- CategoryType 段控件:控制 CategoryType)
- 具有选择器功能的 CategoryTextField:键盘将显示来自类别的数据列表
期望所选类别类型段控件的结果显示基于 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
}
}
}