Reputation: 10738
What I want to do is make a List
with items from a Results
. What I have is a UITableView which was populated from Results
. From this table I want to create a List
when the user selects rows, but for some reason nothing gets appended to the List
when I append items from the Results to the List when the rows are selected.
Here is the code I have:
Realm Object:
import Foundation
import RealmSwift
class Fruit:Object{
dynamic var fruitName:String = ""
dynamic var createdAt = NSDate()
}
ViewController:
var fruits: Results<Fruit>!
var fruitSelectionList: List<Fruit>!
override func viewDidLoad() {
super.viewDidLoad()
updateFruits()
tableFruits.setEditing(true, animated: true)
tableFruits.allowsMultipleSelectionDuringEditing = true
}
func updateFruits(){
fruits = realm.objects(Fruit.self).sorted(byKeyPath: "fruitName")
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return fruits.count
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let index = fruitSelectionList?.index(of: fruits[indexPath.row]) {
try! realm.write {
fruitSelectionList?.remove(at: index)
}
} else {
try! realm.write {
// nothing gets appended here, why?
fruitSelectionList?.append(fruits[indexPath.row])
}
}
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if let index = fruitSelectionList?.index(of: fruits[indexPath.row]) {
fruitSelectionList?.remove(at: index)
}
}
The funny thing is that similar code without using Realm works just fine...
Plain Swift code that works when not using Realm:
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var fruits = ["Apples", "Oranges", "Grapes", "Watermelon", "Peaches"]
var newFruitList:[String] = []
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.allowsSelection = false
tableView.setEditing(true, animated: true)
tableView.allowsMultipleSelectionDuringEditing = true
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return fruits.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = fruits[indexPath.row]
return cell
}
@IBAction func makeSelection(_ sender: Any) {
tableView.allowsMultipleSelectionDuringEditing = true
tableView.setEditing(true, animated: true)
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let item = fruits[indexPath.row]
if let index = newFruitList.index(of: item) {
newFruitList.remove(at: index)
} else {
newFruitList.append(fruits[indexPath.row])
}
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if let index = newFruitList.index(of: fruits[indexPath.row]) {
newFruitList.remove(at: index)
}
}
}
How can I make a List
with some items from a Results
?
FYI - The only reason I need to create the List
is to be able to add and remove items on a table row selection otherwise I would stick with just Results.
Upvotes: 0
Views: 1052
Reputation: 54716
Your code is not the same at all when not using Realm
. The issue has nothing to do with Realm
, it is about wrongly declaring the List
s.
You declare them as implicitly unwrapped optionals (which you shouldn't do in the first place), then try to append a nil
list. You cannot append nil
, you need an empty List
in the first place. If you didn't use safe unwrapping of the optionals, you would get a runtime exception instead of a nil
result.
Declare fruitSelectionList
as an empty List
and you won't have this issue.
var fruits: Results<Fruit>?
var fruitSelectionList = List<Fruit>()
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let index = fruitSelectionList?.index(of: fruits[indexPath.row]) {
fruitSelectionList.remove(at: index)
} else {
fruitSelectionList.append(fruits[indexPath.row])
}
}
Moreover, fruitSelectionList
is not managed by Realm
, since only Results
are automatically updating, so you don't need to put your actions on fruitSelectionList
inside write transactions. You also don't actually need fruitSelectionList
to be of type List
, it could be an Array
as well.
Just a general piece of advice: if you need your selections to be persisted, I would advise you to update your Fruit
model class to have a selected
property of type Bool
and update that property when a row of the tableView is selected.
Upvotes: 2