Использование регистра enume в качестве элемента управления сегментами для отображения типов данных в окне выбора - PullRequest
0 голосов
/ 21 апреля 2020

Я новичок в Swift, и я думал о способе идеального заполнения данных с помощью управления сегментами, который я не пробовал раньше.

V C имеет макет ниже

  • Элемент управления CategoryType: для управления элементом CategoryType)
  • CategoryTextField с функцией выбора: клавиатура покажет список данных из категории

Ожидаемый результат выбранного элемента управления сегмента CategoryType для отображения списка данных на основе CategoryType on pickerview

Этот код находится в режиме проб и ошибок, поскольку у меня не было точного представления о том, как выполнить результат, который я sh должен получить.

 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
    }

Ответы [ 2 ]

0 голосов
/ 21 апреля 2020

не уверен, что я должен задать здесь снова или открыть новый вопрос. Но сначала спросите здесь.

Поскольку ваш код работает хорошо. Я не уверен, как назначить selectedCategory во время добавления новой транзакции в realm.write.

/* TransactionVC */

    var getTransactions : Results<Transaction>!

 override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "TransactionCell", for: indexPath) as! TransactionTableViewCell
        if let transCell = getTransactions?[indexPath.row] {

            cell.categoryLabel.text = transCell.categoryType?.name

        }

        return cell
    }

, используя ваш код выше, когда я хочу добавить новую транзакцию, используя realm.write и cell.categoryLabel.text будет выбрано имя категории, которое может быть «Расход 1–10» / «Доход 1–10»

/* Add VC */

    var selectedCategory : Category?

   func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        categoryTF.text = currentCategories[row].name
//        selectedCategory = CategoryType(rawValue: (currentCategories[row].name))
        selectedCategory = currentCategories[row]
    }

  @IBAction func addTransButtonTapped(_ sender: UIButton) {
        if let currentAccount = selectedAccount {
            do {
                try! realm.write {
                    let newTrans = Transaction()
//                    newTrans.categoryType?.name = selectedCategory?.rawValue as! String
                    newTrans.categoryType? = selectedCategory!
                    newTrans.amount = amountTF.text!

                    currentAccount.ofTransactions.append(newTrans)

                }
            }
        }

        dismiss(animated: true, completion: nil)
    }

Не могли бы вы рассказать мне, как правильно выполнить это?

0 голосов
/ 21 апреля 2020

В вашем контроллере представления вы должны отслеживать категории, которые соответствуют типу, указанному сегментированным элементом управления. Я называю это 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()
        }
    }
}

Когда изменяется сегментированное управляющее значение, вам нужно переосмыслить sh сборщик так, чтобы содержимое отражало выбранный тип категории.

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
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...