Realm et swift UI

Hello,
Quelqu’un aurait-il explorer en détail comment faire une List avec un base Realm avec Swift UI?
Autrement dit comment afficher dans ces nouvelles « TableView » le contenu d’une liste Realm ?

Merci d’avance,

Hello,

https://developer.apple.com/tutorials/swiftui/

Y’a une belle suite de tuto pour la List, ce qui pourrait t’intéresser :wink:

Bonne soirée,

Alexandre

En cherchant j’ai mixé plusieurs infos.

ici l’ajout et l’affichage de la liste fonctionne. Mais la liste ne se met pas à jour automatiquement. Si quelqu’un a une idée

import SwiftUI
import RealmSwift
import Combine

class Dog: Object, Identifiable {
    @objc dynamic var name = ""
    @objc dynamic var age = 0

    override static func primaryKey() -> String? {
        return "name"
    }
}

class SaveDog {
    func saveDog(name: String, age: String) {
        let dog = Dog()
        dog.age  = Int(age) ?? 0
        dog.name = name

        // Get the default Realm
        let realm = try! Realm()

     print(Realm.Configuration.defaultConfiguration.fileURL!)

        // Persist your data easily
        try! realm.write {
        realm.add(dog)
        }

        print(dog)
    }
}

struct DogRow: View {
    var dog = Dog()
    var body: some View {
        HStack {
            Text(dog.name)
            Text("\(dog.age)")
        }
    }

}

class BindableResults<Element>: ObservableObject where Element: RealmSwift.RealmCollectionValue {

    var results: Results<Element>
    private var token: NotificationToken!

    init(results: Results<Element>) {
        self.results = results
        lateInit()
    }

    func lateInit() {
        let realm = try! Realm()
        let dogs = realm.objects(Dog.self)
        token = dogs.observe { [weak self] _ in
            self!.results = self!.results
        }
    }

    deinit {
        token.invalidate()
    }
}

struct Dogs: View {
    
    @State var dogName: String = ""
    @State var dogAge: String = ""

    let saveDog = SaveDog()

    @ObservedObject var dogs = BindableResults<Dog>(results: try! Realm().objects(Dog.self))

        var body: some View {
            VStack {
                Text("Hello World")
            
                        TextField("Name", text: $dogName)
                        TextField("Age", text: $dogAge)
                            .keyboardType(.numberPad)
                        Button(action: {
                            
                            self.saveDog.saveDog(name: self.dogName, age: self.dogAge)
            //                self.savedResults.getRealmResults()
                        }) {
                            Text("Save")
                        }
                        //insert list here to show realm data
                List(dogs.results.sorted(byKeyPath: "age", ascending: true)) { dogs in
                DogRow(dog: dogs)
            }
        }
}
}

struct Dogs_Previews: PreviewProvider {
    static var previews: some View {
        Dogs()
    }
}

Avec ceci la list se met à jour quand on sauve le nouveau Chien. Mais elle « bouge » également quand on tape dans les textfield alors qu’on n’a rien sauvé. Ce soucis est encore à fixer :slight_smile:

class BindableResults<Element>: ObservableObject where Element: RealmSwift.RealmCollectionValue {
    
    @Published var results: Results<Element>
    
    private var token: NotificationToken?

    init(results: Results<Element>) {
        self.results = results
        self.lateInit()
    }

    private func lateInit() {
        let realm = try! Realm()
        let dogs = realm.objects(Dog.self)
        token = dogs.observe { [weak self] _ in
            self!.results = self!.results
        }
    }

    deinit {
        token!.invalidate()
    }
}

Voici le dernier message pour la journée qui fixe le comportement de la list :slight_smile:

J’espère que ça aura aidé.

List {
                    ForEach(self.dogs.results.sorted(byKeyPath: "name", ascending: true), id: \.name) { dogs in
                    DogRow(dog: dogs)
                    }

J’ai commencé à regarder, ça à l’air de marcher :slight_smile:
merci pour ton aide

C’est pas très propre je trouve mais ça fonctionne pour l’affichage.

Par contre ça plante si on delete un élément de la db Realm :frowning:

L’index ne se met pas à jour et ça plante

**Terminating app due to uncaught exception 'RLMException', reason: 'Index 1 is out of bounds (must be less than 1).'**

ca plante aussi quand on insère dans la base deux éléments ayant le même nom… Je pense que c’est lié au fait qu’on détermine le « id » par le nom.
Je vais regarder, mais il faudrait plutôt avoir un id numérique qui s’incrémente de 1 à chaque nouvelle entrée…

swift Ui c’est simple mais pas pour tout quand même :smiley:

Ah non ça c’est parce que la primaryKey de l’object est le name. Pas de lien avec SwiftUI et il n’y a pas de protection contre le risque d’entrer un doublon.

Je pense plutôt que c’est un pb de Realm avec SwiftUI liée aux dynamic var, il y a un truc la dessus sur une issue Github sur le repo Realm Cocoa

Oui ils ont mis en place les Frozen Objects dans la beta 5

Pas encore regardé.

Parfois je me dis qu’implémenter un isDeleted pourrait être une solution. Avec une fonction qui supprime ce qui doit l’être quand on quitte l’app ou la vue.

Ca pourrait être une solution oui !
Perso j’ai juste migré sur CoreData qui a été vraiment bien intégré ^^

Oui mais si par après l’envie est de développer une partie en Webapp ou une App Android ça n’ira pas. C’est pour ça que je reste sur Realm.