Почему отображение данных Realm во встроенном tableView не так просто? - PullRequest
0 голосов
/ 13 апреля 2020

Застрял в отображении данных из Realm в табличном представлении, встроенном в контроллер представления. Вот некоторый код.

Класс модели данных, который обрабатывает схему хранения данных (это приложение для отслеживания финансов):

class Entry: Object {
    @objc dynamic var name: String = ""
    @objc dynamic var amount: Int = 0
    @objc dynamic var date: Date?
    var isExpense: Bool = false

    // initialization block dropped for concise post purposes
}

Класс ячейки:

class FinanceOverviewCell: UITableViewCell {

    @IBOutlet weak var entryNameLabel: UILabel!
    @IBOutlet weak var entryAmountLabel: UILabel!

    func updateData(name: String, amount: String) {
        entryNameLabel?.text = name
        entryAmountLabel?.text = amount
    }
}

Наконец, просмотр контроллера:

import UIKit
import RealmSwift

class FinanceOverviewController: UIViewController {

    @IBOutlet weak var financeOverviewTableView: UITableView!
    @IBOutlet weak var currentBalanceLabel: UILabel!

    var realm = try! Realm()
    let tableEntries = try! Realm().objects(Entry.self)
    let entriesManager = EntriesManager()
    var notificationToken: NotificationToken?

    override func viewDidLoad() {
        super.viewDidLoad()
        print(tableEntries)

        self.financeOverviewTableView.reloadData()
        financeOverviewTableView.delegate = self
        financeOverviewTableView.dataSource = self

        // notification token code block dropped for concise post purposes

        // outlets code block removed for concise post purposes

extension FinanceOverviewController: UITableViewDelegate {    
    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        if editingStyle == .delete {
            realm.beginWrite()
            realm.delete(tableEntries[indexPath.row])
            try! realm.commitWrite()
        }
    }
}

extension FinanceOverviewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return tableEntries.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = financeOverviewTableView.dequeueReusableCell(withIdentifier: "FinanceOverviewCell", for: indexPath) as! FinanceOverviewCell
        let tableData = tableEntries[indexPath.row]

        cell.updateData(name: tableData.name, amount: String(tableData.amount))

        return cell
    }
}

Проблема в cellForRowAt fun c в контроллере вида. Каким-то образом, хотя tableData каждый раз содержит что-то правильное для добавления строки, он просто ничего не добавляет. На экране приложения я вижу, что появляется еще одна строка с метками-заполнителями.

enter image description here

В чем может быть проблема? Я прочитал некоторые ссылки, а также просмотрел официальный пример , но не нашел никакого специального решения для этого случая.

Спасибо за поддержку.

1 Ответ

1 голос
/ 13 апреля 2020

На самом деле работать с Realm не сложно, я попытался воспроизвести ваш код, и все работает нормально. Я думаю, что это связано с NotificationToken , потому что каждый раз, когда ваша коллекция изменяется, токен уведомления запускает блок кода, и я не знаю, как вы обновляете свой tableView. Я предлагаю вам использовать это расширение, я использую его месяцами, и это лучший способ принять UITableView с NotificationToken в Realm:

    extension UITableView {
  func applyChanges<T>(changes: RealmCollectionChange<T>) {
    switch changes {
      case .initial: reloadData()
      case .update(let results, let deletions, let insertions, let updates):
        let fromRow = { (row: Int) in return IndexPath(row: row, section: 0) }
        beginUpdates()
        insertRows(at: insertions.map(fromRow), with: .automatic)
        reloadRows(at: updates.map(fromRow), with: .automatic)
        deleteRows(at: deletions.map(fromRow), with: .automatic)
        endUpdates()
      case .error(let error): fatalError("\(error)")
    }
  }
}

пример использования:

notificationToken = tableEntries.addNotificationBlock { changes in
  financeOverviewTableView.applyChanges(changes)
}

source : https://academy.realm.io/posts/meetup-jp-simard-mastering-realm-notifications/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...