J'ai quelques objets gérés par domaine dans mon application qui doivent conserver une trace de l'horodatage dans lequel ils ont été modifiés pour la dernière fois. J'aurais pu mettre en œuvre le modèle de programmation du référentiel pour cela, ou je pourrais juste me rappeler de définir la propriété chaque fois que je change quelque chose sur ces objets (ce qui est une idée de repli, aussi horrible que cela puisse paraître). Ce que j'ai fait est de créer un objet singleton qui surveille les collections d'objets pour lesquels je veux garder un horodatage de "dernière modification". Ceci est démarré au démarrage de l'application et garde un oeil sur les collections pour toutes les modifications.Éviter les notifications de modification récursques du domaine
Le « flux » général est:
- attente de notification de changement
- Le changement, boucle les indices modifiés
- Vérifiez l'index existe avant d'essayer d'accéder à l'objet (au cas où)
realm.write
une nouvelle date de dernière modification à l'objet
Comme vous pouvez le deviner probablement déjà (un nd comme je le soupçonnais), ce realm.write pour mettre à jour mon dernier horodatage modifié, puis crée une nouvelle notification de changement, qui à son tour rend la mise à jour d'horodatage à nouveau. Donc, il finit juste en boucle pour toujours après le premier changement.
Vous cherchez des options pour résoudre ce problème.
Voici ce que j'ai mis en œuvre:
class RealmCollectionLastModifiedMonitor {
static let shared = RealmCollectionLastModifiedMonitor()
private var formObjectNotificationToken: NotificationToken?
private init() {
startMonitoring()
}
deinit {
stopMonitoring()
}
func startMonitoring() {
let realm = try! Realm()
let caseforms = realm.objects(CaseForm.self)
formObjectNotificationToken = caseforms.addNotificationBlock { [weak self] (changes: RealmCollectionChange) in
switch changes {
case .initial:
// Do nothing for now - as i've not worked out what this is :P
break
case .update(_, let deletions, let insertions, let modifications):
// Some debug output
print("Form collection change: Deletions = \(deletions.count), Insertions = \(insertions.count), Modifications = \(modifications.count)")
// Loop the modificated indexes, get a reference to the form, then update the last modified timestamp
for i in modifications {
if caseforms.indices.contains(i) {
do {
try realm.write {
caseforms[i].lastModified = Date()
}
} catch {
print("Failed to update modified date")
}
}
}
break
case .error(let error):
// Do nothing for now - If a write fails, we could rollback, but it's not uber-important
break
}
}
}
func stopMonitoring() {
formObjectNotificationToken = nil
}
}
Merci James. Pensez-vous que cela pourrait être jumelé avec les notifications de collection pour insérer et supprimer? Donc, si j'ai un moniteur de collection pour supprimer et insérer, qui alors créer (ou supprimer) des notifications d'objet pour les objets individuels? Évidemment, j'ai aussi besoin d'enregistrer des notifications pour les objets existants au démarrage de l'application. J'essaierai demain, mais j'ai pensé que je poserais la question juste au cas où vous savez déjà que c'est une idée stupide et je ne devrais même pas l'essayer: P – TRG
Oui, mais vous devez vous assurer que vous ajoutez un bloc de notification à l'objet en dehors du rappel de notification de collection. Une façon simple de le faire est simplement de faire un 'DispatchQueue.main.async {self.monitor (caseForm)}' dans le rappel de notification de collection. –
Génial, n'aurait pas pensé à faire fonctionner le moniteur en dehors du bloc, merci James! – TRG