Reputation: 71
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.
Upvotes: 0
Views: 84
Reputation: 164
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/
Upvotes: 1