Design für eine Chat-App mit Core Data

8

Ich schreibe eine Chat-App und bin dabei, meine Datenbank zu ändern, um Core Data zu verwenden. Ich verwende momentan sqlite direkt, aber ich möchte die iCloud-Funktion nutzen, um die Engine zu wechseln.

Meine Haupttabelle heißt Eintrag mit folgenden Eigenschaften:

%Vor%

wo 'Typ' sein kann:

%Vor%

Meine App unterstützt auch den Chat mit mehreren Benutzern (daher die Typen "Benutzer beigetreten" / "Benutzer links"). Alle Nachrichten gehören zu derselben Konversation (nur Multichat), haben eine gültige Eigenschaft 'session'.

In meinem Chat-Verlauf ist mein Problem, wie man "load more" wie Apple in der SMS-App erreicht: Ich werde basierend auf 'username=%@ AND session IS NULL' oder 'session=%@' abfragen, um diesen Verlauf anzuzeigen und ein LIMIT von 50 sortiert zu verwenden durch umgekehrten "Zeitstempel". Ich möchte dann eine Schaltfläche "Mehr laden" haben, die die nächsten 50 Nachrichten lädt - ich bin nicht sicher, wie es mit Core Data geht.

Meine nächste Frage ist, wie die Liste der Konversationen angezeigt werden soll. Im Moment mit rohen SQLite, führe ich eine Verbindung bei 2 Abfragen durch: die erste ist die letzte Nachricht jedes Benutzers und die zweite ist die letzte Nachricht jeder Mehrbenutzer-Konversation. Ich sortiere sie dann alle nach Datum. Da Core Data keine Joins unterstützt, bin ich mir nicht sicher, wie ich diese Abfrage durchführen soll.

Danke

    
Gilad Novik 29.03.2012, 22:04
quelle

2 Antworten

14

Mit einer App, die genau das gleiche macht, hier meine Einsichten.

Zunächst sollten Sie Coredata und Multithreading mit Bedacht betrachten, bevor Sie programmieren. Wenn Sie Hilfe brauchen, lassen Sie es mich wissen.

Das Modell

Sie arbeiten mit Entitäten in Coredata, die wie Tabellen in sqlite behandelt werden können, aber auf eine abstraktere Art und Weise. Sie sollten überprüfen Apples Dokumentation dafür.

Wir finden in Ihrem Fall mindestens drei verschiedene Entitäten: Benutzer, Unterhaltung und Nachricht. (Seien Sie vorsichtig mit dem letzten, ich hatte ein Problem mit der Entität namens Nachricht beim Importieren des SMS-Frameworks, sollten Sie in Betracht ziehen, den Namen der Entität voranzutreiben ..)

Ein Problem mit coredata ist, dass Sie Arrays nicht direkt speichern können (vielleicht mit einem unbekannten Typ), aber trotzdem. Also zwei Lösungen, um Ihre Benutzer zu speichern: Entweder in einem NSString, wenn sie von comas begrenzt werden, und ein einfacher Regex oder Split gibt Ihnen die Anzahl der Benutzer.

So könnte Ihr Modell aussehen:

%Vor%

Die Unterhaltung muss eine Beziehung zwischen mehreren Nachrichten und einer Nachricht enthalten, die eine direkte Beziehung zu Konversation darstellt.

- BEARBEITEN

Wenn Sie die letzte Nachricht einer Konversation genau wie die Nachrichten-App (oder meine App) anzeigen möchten, können Sie eine Beziehung mit der Nachricht hinzufügen. Die Nachricht wird nicht zweimal in der Datenbank / Coredata gespeichert. In der Tat, Sie erstellen ein Coredata-Objekt (in diesem Fall eine Nachricht) und dass Sie es zu einer Konversation hinzufügen, was im Inneren passiert ist, dass eine Konversation die Coredata-ID für das Objekt speichern. Das Hinzufügen einer Beziehung für diese Nachricht (lastMessage) speichert nur eine andere ID und kein anderes Objekt.

- Ende von EDIT

Benutzer unterscheiden sich ein wenig, weil sie Teil mehrerer Konversationen sein können (wegen der Gruppenunterhaltung). Deshalb brauchen Sie eine Viele-zu-Viele-Beziehung.

Sie können so viele Attribute hinzufügen, wie Sie möchten, aber das ist die Mindestanforderung!

  1. Implementierung

dann in Ihrem Code, wenn Sie das Verhalten von iMessage nachahmen möchten, hier ist, was ich getan habe:

im ersten Controller, wo Sie die gesamte Konversation sehen können: Verwenden Sie einen NSFetchedResultController. Die Abfrage sollte nur über die Entität Conversation erfolgen.

Wenn ich auf eine Zeile klicke, habe ich in der neuen Ansicht das Konversationsobjekt und einen weiteren NSFtechedResultController gefunden. Ich frage dann nur die Entity Message, aber mit einem Prädikat, das angibt, dass ich nur diese Konversation möchte.

Wenn Sie überprüfen möchten, ob in meiner App die Fluidität angezeigt wird, gehen Sie zu diesem Link.

BEARBEITEN

  1. Code-Snippet, um die letzte Nachricht einer Konversation zu finden

Achtung: Dies ist eine vorläufige Antwort, bevor Sie eine bessere Möglichkeit finden, dies zu tun (d. h. wenn Sie geholte Eigenschaften verwenden)

%Vor%

- Ende von EDIT

Hoffe diese Hilfe!

Pierre

    
Pierre 28.05.2012, 14:12
quelle
1

Erstens ist dein mentales Modell alles falsch. Sie sollten Kerndaten nicht als SQL-Datenbank betrachten. Ja, meistens wird SQL verwendet, es handelt sich jedoch lediglich um ein Implementierungsdetail. Sie sollten in Bezug auf Objektdiagramme denken.

Sehen Sie sich als Nächstes für Ihr Problem "50 Elemente" NSFetchRequest an. Sie können angeben, wo (fetchOffset) gestartet werden soll und wie viele Elemente abgerufen werden sollen (fetchLimit). Es gibt auch andere Möglichkeiten für Sie. Wenn Ihre Gesamtzahl der Elemente relativ klein ist, können Sie einfach das gesamte Array abrufen (und nur so viele Fehler gleichzeitig beheben - siehe fetchBatchSize).

Berücksichtigen Sie beim "Join", wie Objekte miteinander in Beziehung stehen, und nicht bei Join mit Datenbanktabellen. Leider verstehe ich nicht, was Sie mit diesem Teil der Frage erreichen wollen. Sie können jedoch "verbundene" Tabellen nachahmen, indem Sie bei der Bildung Ihres Prädikats die Punktnotation verwenden.

BEARBEITEN

Wenn Sie ein Konversationsobjekt erstellen, können Sie eine to-many-Beziehung zu etwas wie "Teilnehmer" hinzufügen, bei dem es sich um eine Gruppe aller Benutzer handelt, die an dieser Konversation teilgenommen haben. Die Umkehrung wäre auch eine to-many-Beziehung in "user", die alle Konversationen enthält, an denen der Benutzer teilgenommen hat (ich nehme an, dass Ihre Datenbank mehrere Benutzer hat).

Um also alle Konversationen zu erhalten, an denen ein bestimmter Benutzer teilgenommen hat, könnten Sie so etwas wie "Participant" mit einem Prädikat wie "ALL participants.username =% @"

holen     
Jody Hagins 08.05.2012 14:03
quelle

Tags und Links