Je travaille sur une méthode de synchronisation des données de base stockées dans une application iPhone entre plusieurs périphériques, tels qu'un iPad ou un Mac. Il n'y a pas beaucoup (voire pas du tout) d'infrastructure de synchronisation à utiliser avec Core Data sur iOS. Cependant, j'ai réfléchi au concept suivant:
Y a-t-il quelque chose d'extraordinaire auquel je dois penser? J'ai examiné les structures REST telles que ObjectiveResource , ressource principale et RestfulCoreData . Bien sûr, ils fonctionnent tous avec Ruby sur Rails, auquel je ne suis pas lié, mais c'est un endroit pour commencer. Les principales exigences de ma solution sont les suivantes:
J'ai réfléchi à plusieurs défis:
Y a-t-il autre chose qui me manque ici? Quels types de cadres dois-je examiner pour rendre cela possible?
Je suggère de lire attentivement et de mettre en œuvre la stratégie de synchronisation discutée par Dan Grover lors de la conférence iPhone 2009, disponible ici en format PDF.
Ceci est une solution viable et n'est pas si difficile à mettre en œuvre (Dan l'a implémentée dans plusieurs de ses applications), chevauchant la solution décrite par Chris. Pour une discussion théorique approfondie sur la synchronisation, voir l'article de Russ Cox (MIT) et William Josephson (Princeton):
Synchronisation de fichier avec des paires de temps vectorielles
qui s’applique aussi bien aux données de base avec quelques modifications évidentes. Ceci fournit une stratégie de synchronisation beaucoup plus robuste et fiable, mais nécessite plus d'effort pour être mis en œuvre correctement.
MODIFIER:
Il semble que le fichier pdf de Grover n'est plus disponible (lien brisé, mars 2015). UPDATE: le lien est disponible via la machine de retour ici
Le framework Objective-C appelé ZSync et développé par Marcus Zarra est déconseillé, car iCloud semble enfin prendre en charge la synchronisation correcte des données de base.
J'ai fait quelque chose de similaire à ce que vous essayez de faire. Laissez-moi vous dire ce que j'ai appris et comment je l'ai fait.
Je suppose que vous avez une relation un-à-un entre votre objet Core Data et le modèle (ou schéma de base de données) sur le serveur. Vous souhaitez simplement que le contenu du serveur soit synchronisé avec les clients, mais les clients peuvent également modifier et ajouter des données. Si j'ai bien compris, alors continuez à lire.
J'ai ajouté quatre champs d'aide à la synchronisation:
Sur le client, ajoutez du code pour définir sync_status sur 1 sur votre objet de modèle chaque fois que quelque chose change et doit être synchronisé sur le serveur. Les nouveaux objets de modèle doivent générer un GUID.
La synchronisation est une requête unique. La demande contient:
Le serveur obtient la demande et fait ceci:
L'application reçoit la réponse et fait ceci:
J'espère que ça aide. J'ai utilisé l'enregistrement et le modèle Word de manière interchangeable, mais je pense que vous avez compris l'idée. Bonne chance.
Si vous êtes toujours à la recherche d'un moyen d'aller plus loin, jetez un coup d'œil au téléphone mobile Couchbase. Cela fait essentiellement tout ce que vous voulez. ( http://www.couchbase.com/nosql-databases/couchbase-mobile )
Comme @Cris, j’ai implémenté class pour la synchronisation entre client et serveur et résolu jusqu’à présent tous les problèmes connus (envoi/réception de données vers/depuis le serveur, conflits de fusion fondés sur des horodatages, suppression des entrées en double dans des conditions de réseau peu fiables, synchronisation des données imbriquées, etc. fichiers etc ..)
Vous venez d'indiquer à la classe quelle entité et quelles colonnes doit-elle être synchronisée et où se trouve votre serveur.
M3Synchronization * syncEntity = [[M3Synchronization alloc] initForClass: @"Car"
andContext: context
andServerUrl: kWebsiteUrl
andServerReceiverScriptName: kServerReceiverScript
andServerFetcherScriptName: kServerFetcherScript
ansSyncedTableFields:@[@"licenceNumber", @"manufacturer", @"model"]
andUniqueTableFields:@[@"licenceNumber"]];
syncEntity.delegate = self; // delegate should implement onComplete and onError methods
syncEntity.additionalPostParamsDictionary = ... // add some POST params to authenticate current user
[syncEntity sync];
Vous pouvez trouver la source, un exemple pratique et d’autres instructions ici: github.com/knagode/M3Synchronization .
Je pense qu'une bonne solution au problème de GUID est "système d'identification distribuée". Je ne sais pas quel est le terme correct, mais je pense que c'est ainsi que les documents serveur MS SQL l'appelaient (SQL utilise/a utilisé cette méthode pour les bases de données distribuées/synchronisées). C'est assez simple:
Le serveur attribue tous les identifiants. Chaque fois qu'une synchronisation est effectuée, la première chose vérifiée est "Combien d'ID me reste-t-il sur ce client?" Si le client est à l'état bas, il demande au serveur un nouveau bloc d'identifiants. Le client utilise ensuite les identifiants de cette plage pour les nouveaux enregistrements. Cela fonctionne très bien pour la plupart des besoins, si vous pouvez affecter un bloc suffisamment volumineux pour qu'il ne soit "jamais" épuisé avant la prochaine synchronisation, mais pas si grand que le serveur ne s'épuise pas dans le temps. Si le client s'épuise, le traitement peut être assez simple, dites simplement à l'utilisateur "désolé, vous ne pouvez pas ajouter plus d'éléments jusqu'à ce que vous synchronisiez" ... s'ils ajoutent autant d'éléments, ils ne devraient pas se synchroniser pour éviter les données obsolètes. questions quand même?
Je pense que cela est supérieur à l'utilisation de GUID aléatoires, car les GUID aléatoires ne sont pas sûrs à 100% et doivent généralement être beaucoup plus longs qu'un identifiant standard (128 bits par rapport à 32 bits). Vous avez généralement des index par ID et vous conservez souvent les numéros d’identification en mémoire. Il est donc important de les garder petits.
Je ne voulais pas vraiment poster comme réponse, mais je ne savais pas que quelqu'un le verrait comme un commentaire, et je pense que c'est important pour ce sujet et non inclus dans d'autres réponses.
Je viens de publier la première version de ma nouvelle API de synchronisation Core Data Cloud, appelée SynCloud. SynCloud présente de nombreuses différences avec iCloud car il permet une interface de synchronisation multi-utilisateurs. Il est également différent des autres API de synchronisation car il permet la création de données relationnelles multi-tables.
Pour en savoir plus, visitez le site http://www.syncloudapi.com
Construit avec iOS 6 SDK, il est très à jour du 27/09/2012.
Avis à l'utilisateur de mettre à jour les données via une notification Push. Utilisez un fil d’arrière-plan dans l’application pour vérifier les données locales et les données sur le serveur cloud, tandis que le changement se produit sur le serveur, modifiez les données locales, et inversement.
Je pense donc que la partie la plus difficile consiste à estimer les données de quel côté est invalide.
J'espère que cela peut vous aider
Tout d’abord, vous devez repenser le nombre de données, de tables et de relations que vous aurez. Dans ma solution, j'ai implémenté la synchronisation via des fichiers Dropbox. J'observe les changements dans le fichier MOC principal et enregistre ces données dans des fichiers (chaque ligne est enregistrée sous json gzipped). Si une connexion Internet fonctionne, je vérifie si des modifications ont été apportées à Dropbox (Dropbox me donne les modifications de type delta), je les télécharge et les fusionne (les dernières victoires), puis je place les fichiers modifiés. Avant la synchronisation, je mets le fichier de verrouillage sur Dropbox pour empêcher les autres clients de synchroniser des données incomplètes. Lors du téléchargement des modifications, il est prudent de ne télécharger que des données partielles (par exemple, une connexion Internet perdue). Lorsque le téléchargement est terminé (complètement ou partiellement), les fichiers sont chargés dans Core Data. Lorsqu'il y a des relations non résolues (tous les fichiers ne sont pas téléchargés), le chargement des fichiers est arrêté et le téléchargement est terminé plus tard. Les relations sont stockées uniquement en tant que GUID, ce qui me permet de vérifier facilement quels fichiers doivent être chargés pour garantir l’intégrité complète des données. La synchronisation commence après la modification des données de base. S'il n'y a pas de modifications, il vérifie les modifications sur Dropbox toutes les quelques minutes et au démarrage de l'application. De plus, lorsque des modifications sont envoyées au serveur, j'envoie une diffusion à d'autres appareils pour les informer de ces modifications, afin qu'ils puissent se synchroniser plus rapidement. Chaque entité synchronisée a la propriété GUID (guid est également utilisé comme nom de fichier pour les fichiers d'échange). J'ai également une base de données Sync où je stocke la révision Dropbox de chaque fichier (je peux la comparer lorsque le delta de Dropbox réinitialise son état). Les fichiers contiennent également le nom de l'entité, l'état (supprimé/non supprimé), guid (identique au nom du fichier), la révision de la base de données (pour détecter les migrations de données ou éviter la synchronisation avec des versions jamais app) et bien sûr les données (si la ligne n'est pas supprimée).
Cette solution fonctionne pour des milliers de fichiers et environ 30 entités. Au lieu de Dropbox, je pourrais utiliser le magasin de clé/valeur comme REST service Web que je souhaite créer ultérieurement, mais je n’ai pas le temps de le faire :) Pour l’instant, ma solution est plus fiable que iCloud et , qui est très important, j’ai le plein contrôle sur la façon dont cela fonctionne (principalement parce que c’est mon propre code).
Une autre solution consiste à enregistrer les modifications MOC en tant que transactions: le nombre de fichiers échangés avec le serveur sera beaucoup moins important, mais il sera plus difficile de charger le chargement initial dans le bon ordre dans des données de base vides. iCloud fonctionne de cette façon, et d'autres solutions de synchronisation ont une approche similaire, par exemple TICoreDataSync .
-- MISE À JOUR
Après un moment, j'ai migré vers Ensembles - Je recommande cette solution plutôt que de réinventer la roue.