I have 2 models (a "Category" model and an "Item" model) such as following. “Category” has a to-many relationship to “Item” via the property “items”
I would like to get the sorted data of “category” and “item” by its "order" but how can I do it?
Category.swift
import Foundation
import RealmSwift
class Category: Object {
@objc dynamic var name: String = ""
@objc dynamic var order: Int = 0 // use this for sorting
let items = List<Item>
}
Item.swift
import Foundation
import RealmSwift
class Item: Object {
@objc dynamic var name: String = ""
@objc dynamic var order: Int = 0 // use this for sotging
let category = LinkingObjects(fromType: Category.self, property: "items")
}
I can only sort the ‘’category’’ by its order but I can’t do it with the ‘’items’’
let categories = realm.objects(Category.self).sorted(byKeyPath: "order", ascending: true)
You really aren't too far off.
Realm Results objects can be unordered so it's important to have a strategy to keep Results objects loaded in the order you want. As is, you've got that on your category objects with this
@objc dynamic var order: Int = 0 // use this for sorting
On the other hand, Realm List objects MAINTAIN their order of insertion
class Category: Object {
let items = List<Item>
So if chicken was added to a category items list, and then pork, that order will stick; chicken at index 0, pork at index 1.
Meat
chicken
pork
That's covered in the Realm Documentation
List properties are guaranteed to preserve their order of insertion.
Because of that, when populating a tableView as in the question, you can use the tableView titleForHeaderInSection to get the section names (Categories: Meat, Vegetables, Fruit) from the results object (because they were ordered when the results were loaded from Realm)
Then for the rows within each section, you can read the Category->items List for the items, which will be ordered by their insertion because they are in a List.
For completeness, here's the code for handling the section of a tableView
//
//handle sections
//
func numberOfSections(in tableView: UITableView) -> Int {
return self.yourCategoryResults.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
let title = self.yourCategoryResults[section].name //the section title
return title
}
and then the code to handle the rows in each section
//
//handleTableView rows
//
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let rowsInSection = self.yourCategoryResults[section].items.count
return rowsInSection
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellReuseIdentifier", for: indexPath)
let item = self.yourCategoryResults[indexPath.section].items[indexPath.row]
let text = item.name
cell.textLabel?.text = text
return cell
}