Got stuck with displaying the data from Realm in the table view, embedded in a view controller. Here's some code.
Data model class that handles the scheme of how the data is stored (this is a finance tracking app):
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
}
Cell class:
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
}
}
Finally, view controller:
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
}
}
The problem is in cellForRowAt func in the view controller. Somehow, though tableData each time holds something proper to add a row, it simply adds nothing. In the app screen I see it as yet another row with placeholder labels comes in.
What could be the issue? I read some reference as well as looked through official example but didn't see any special solution for this case.
Thank you for the support.
Actually working with Realm is not hard, I tried to reproduce your code and everything is work fine. I think it's related to NotificationToken, because every time your collection changed, notification token run block of code and I don't know how you update your tableView. I suggest you to use this extension, I'm using it for months and it's the best way to adopt UITableView with Realm's NotificationToken:
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)")
}
}
}
example of usage:
notificationToken = tableEntries.addNotificationBlock { changes in
financeOverviewTableView.applyChanges(changes)
}
source: https://academy.realm.io/posts/meetup-jp-simard-mastering-realm-notifications/