Synchronisation Multi-Clients <=> Serveur

muqaddarmuqaddar Administrateur
juin 2010 modifié dans Objective-C, Swift, C, C++ #1
Bonsoir à  tous,

Dans mon application iPhone, j'utilise déjà  la synchronisation serveur => client pour une série de modifications ou suppressions possibles sur quelques tables de données SQL.

En clair, j'ai développé un WebServices en Ruby sur mon site Internet où j'ai une administration qui enregistre mes actions dans une table. Ensuite, je génère des enregistrements SQL et une version associée pour ces changements.

Depuis l'iPhone, lorsque je lance une synchronisation dans mon application, j'appelle une URL avec contrôle de version BDD qui me renvoie un fichier XML que je parse, et qui génère mes requêtes SQL en local pour modifier ma base locale.

Jusque là  tout va bien.

En revanche, je vais essayer de faire la pirouette inverse, à  savoir envoyer les données de la base iPhone vers le serveur. A première vue, le mieux est aussi de générer un fichier XML en local et de l'envoyer en requête HTTP POST ? A l'arrivée, je peux faire un parser en Ruby qui fait le boulot inverse ? Quelle est la meilleure méthode pour expédier cet XML sur le serveur ? Quelles sont les règles de base pour ne pas envoyer toute la base du client à  chaque fois ? Faut-il également enregistrer toutes ses actions ou se servir de champs created_at, updated_at dans chaque table par exemple ? Je suppose qu'il y a des choses à  faire et ne pas faire en synchronisation.

Pour l'instant, le client ne peut modifier ses données que sur l'iPhone mais pourquoi pas un jour sur le serveur... En attendant, ça lui servira de backup s'il a un soucis avec son app client.

Bref, si vous avez des pistes, ou bien un bon lien (que j'ai du mal à  trouver) pour faire de la synchronisation avec Cocoa, n'hésitez pas.
«1

Réponses

  • StephSteph Membre
    janvier 2010 modifié #2
    Salut,

    Tu peux regarder du coté de JSON aussi. Ca te permet de dialoguer avec ton serveur et l'avantage de JSON c'est que tu peut lui envoyer des objets genre Array. Ca sera peut-être moins lourd à  gérer que du XML à  voir.

    Tu peux jeter un oeil par là  :

    http://www.mobileorchard.com/tutorial-json-over-http-on-the-iphone/

    ou là 

    http://iphonedevelopertips.com/networking/iphone-json-flickr-tutorial-part-1.html

    Tu trouveras pas mal d'infos sur le web.

    Moi j'utilise JSON pour discuter entre mon javascript et mon PHP et c'est top.

    ++
  • muqaddarmuqaddar Administrateur
    11:45 modifié #3
    Je vais regarder ce JSON, je ne connais pas (à  part le nom). Merci pour cette info.
    D'autres avis sur la syncho sont les bienvenus. ;)
  • AliGatorAliGator Membre, Modérateur
    11:45 modifié #4
    J'utilise du JSON également, bien plus facile à  manipuler pour ce genre d'échanges de données que du XML.
    En gros le JSON permet d'échanger des données simples (tableaux, dictionnaires, ou valeurs comme des chaines, entiers, flottants, booléens). Voir le site json.org qui est super simpliste... mais largement suffisant, puisqu'il explique uniquement avec 3-4 images toutes les possibilités de JSON. Simple mais efficace.

    Il existe une "lib" pas mal répandue en plus pour l'iPhone : SBJSON.
    Elle consiste juste en quelques fichiers et son utilisation est super simple grace au fait que l'auteur a fait des catégories sur NSString, NSDictionary, et NSArray.

    Du coup ça te permet, quand tu veux envoyer un NSArray à  ton serveur, de faire [tt][monArray JSONString][/tt] pour récupérer la  NSString JSON à  envoyer au serveur. Pareil avec NSDictionary, NSArray, etc.
    De même dans l'autre sens quand tu reçois une réponse JSON de la part de ton serveur, tu fais juste [tt][chaineRetourneeParServeur JSONValue][/tt] et ça te retourne directement le NSArray ou NSDictionary correspondant à  la représentation JSON récupérée.

    Côté serveur, il y a plein de librairies PHP pour générer du JSON à  la volée. Côté Javascript (par exemple requêtes AJAX), évidemment c'est natif, puisque c'est de là  que vient le JSON (JavaScript Object Notation). Côté Ruby, je sais pas trop mais à  mon avis soit c'est intégré soit y'a plein de libs aussi.
  • StephSteph Membre
    11:45 modifié #5
    Php supporte Json en natif depuis la 5.2.1 je crois :)

    Tu as deux fonctions très utiles : json_encode et json_decode

    C'est très simple à  utiliser.

    En revanche, comme Ali, pour Ruby je ne sais pas mais je crois avec déjà  vu que ct supporté.

    May the force be with you
  • muqaddarmuqaddar Administrateur
    11:45 modifié #6
    Bon, je vous remercie pour ces infos.
    J'ai trouvé des librairies Ruby JSON. Je vais étudier tout cela et surtout bien rélféchir à  la logique de la synchronisation...

    Pour info, j'ai 40 tables dans l'application.
    - 6 à  synchroniser serveur => client
    - 9 à  synchroniser serveur <=> client
  • 11:45 modifié #7
    dans 1264070147:

    Du coup ça te permet, quand tu veux envoyer un NSArray à  ton serveur, de faire [tt][monArray JSONString][/tt] pour récupérer la  NSString JSON à  envoyer au serveur. Pareil avec NSDictionary, NSArray, etc.
    De même dans l'autre sens quand tu reçois une réponse JSON de la part de ton serveur, tu fais juste [tt][chaineRetourneeParServeur JSONValue][/tt] et ça te retourne directement le NSArray ou NSDictionary correspondant à  la représentation JSON récupérée.



    Je sens que je vais m'y mettre :) pour l'instant j'ai toujours fonctionné en XML.
  • muqaddarmuqaddar Administrateur
    11:45 modifié #8
    @Ali

    J'ai téléchargé et installé JSON dans mon app.
    Mais je suis sur 2 tutorials qui ne procèdent pas de la même manière.

    Ici : http://iphonedevelopertips.com/networking/iphone-json-flickr-tutorial-part-1.html
    Point de SBJSON object, on utilise JSONValue sur la string récupérée.

    Ici : http://blog.zachwaugh.com/post/309924609/how-to-use-json-in-cocoaobjective-c
    Un objet SBJSON qui sert pour le parsing.

    Bref, y-t-il 2 façons de faire pour le décodage d'une string JSON ?
  • AliGatorAliGator Membre, Modérateur
    janvier 2010 modifié #9
    Il y a effectivement plusieurs façons de l'utiliser, cf la doc.

    1) Méthode 1, utiliser les objets de parsing et génération
    - Tu as une classe SBJsonWriter, qui permet de générer du JSON. Il possède un protocole associé ([tt]@interface SBJsonWriter : SBJsonBase <SBJsonWriter> ... @end[/tt]) qui déclare ses méthodes. Ainsi tu as d'un côté un protocole décrivant les méthodes qu'un objet implémente quand il se conforme à  SBJsonWriter, et un objet qui implémente effectivement ces méthodes.
    - Sur le même principe, il existe une classe SBJsonParser, qui permet de parser une chaà®ne JSON pour recréer un objet, et utilise le même principe comme tu le vois ([tt]@interface SBJsonParser : SBJsonBase <SBJsonParser> ... @end[/tt])
    - Et tu as une classe SBJSON (celle utilisé dans le cas du lien 2 que tu as mis) qui est une sorte de wrapper, qui implémente les deux protocoles SBJsonParser et SBJsonWriter. C'est juste pour une facilité si tu veux : si tu regardes le .h et .m tu verras en effet que cette classe contient une variable d'instance SBJsonWriter et une v.i. SBJsonParser, et que les méthodes des protocoles éponymes se contentent de forwarder les appels à  ces objets internes. Ca te permet d'avoir dans ton code de ton côté qu'un seul objet pour faire les deux, parsing et génération.

    Donc déjà  là  tu as le choix, entre utiliser les objets de premier niveau SBJsonWriter/SBJsonParser quand tu veux générer ou parser du JSON, ou utiliser un objet unique SBJSON qui encapsule les deux possibilités à  la fois.

    2) Méthode 2 : utiliser les catégories
    Mais là  où l'auteur de la lib a eu une bonne idée, c'est qu'en plus de ces classes permettant de parser une chaà®ne JSON que tu lui passes, ou générer du JSON d'après un objet, il a rajouté une catégorie sur NSString (ajout d'une méthode [tt]-(id)JSONValue[/tt]) ainsi qu'une catégorie sur NSObject (ajout d'une méthode [tt]-(NSString*)JSONRepresentation[/tt]).

    Et que font ces catégories ? Simple !
    - La méthode JSONValue de NSString, en interne elle crée un SBJsonParser, lui passe la NSString (self) en paramètre, et retourne l'objet en résultat.
    - La méthode JSONRepresentation de NSObject, en interne elle crée un SBJsonWriter, lui passe l'objet (self) en paramètre, et retourne la chaà®ne générée.

    Du coup grâce à  ces catégories, ça fait beaucoup plus "objet" et beaucoup plus propre comme code, et ça t'évite de créer ton SBJsonParser et SBJsonWriter ou ton objet SBJSON.



    Après, tu as tous les choix, utiliser la classe/wrapper SBJSON, utiliser plus directement un SBJsonWriter et/ou un SBJsonParser, ne pas t'embêter et passer directement par les catégories... moi perso je m'embête pas, les deux méthodes des catégories font tout ce qu'il faut pour moi (et donnent l'impression que JSON est intégré à  Cocoa et aux classes existantes) donc pourquoi s'en priver ?
  • SilentGobSilentGob Membre
    11:45 modifié #10
    je sais que j'arrive un peu après la bataille mais je plussoie JSON (et je le plussoie encore une fois en bon allergique au XML que je suis). Quand je vois ce que des gens font passer dans du XML bien verbeux alors que ça passe aussi bien ( voir mieux) dans du JSON ... j'te les fouetterai les gens qui utilisent XML à  tord et à  travers >:)

    (de plus JSON commence à  être très bien vu  <3 )
  • muqaddarmuqaddar Administrateur
    11:45 modifié #11
    Merci de m'avoir décortiqué ça Ali ! 
    En fait, j'étais sur la doc Ruby-Json pendant ce temps.  ;)

    Je regarde tout ça demain et vous tiens au courant.
  • muqaddarmuqaddar Administrateur
    11:45 modifié #12
    dans 1264100849:

    Après, tu as tous les choix, utiliser la classe/wrapper SBJSON, utiliser plus directement un SBJsonWriter et/ou un SBJsonParser, ne pas t'embêter et passer directement par les catégories... moi perso je m'embête pas, les deux méthodes des catégories font tout ce qu'il faut pour moi (et donnent l'impression que JSON est intégré à  Cocoa et aux classes existantes) donc pourquoi s'en priver ?


    Oui, tu as raison. Si on a le gâteau et la cerise, autant commencer à  manger la cerise ! ;)
    Elle est dessus en plus. :)
  • muqaddarmuqaddar Administrateur
    11:45 modifié #13
    Un peu de code Ruby côté serveur pour s'endormir... ça peut intéresser.

    Petit test :

    class SyncController &lt; ApplicationController<br />&nbsp; &nbsp; <br />&nbsp; def index&nbsp; <br />&nbsp; &nbsp; @countries = Country.find :all<br />&nbsp; &nbsp; respond_to do |format|<br />&nbsp; &nbsp; &nbsp; format.json { render :json =&gt; @countries } <br />&nbsp; &nbsp; end<br />&nbsp; end<br /><br />end
    


    nous donne :

    [{"it_name":null,"de_name":null,"en_name":"France","id":1,"status":1,"image":"France.gif","fr_name":"France","es_name":null}, {"it_name":null,"de_name":null,"en_name":"Spain","id":2,"status":1,"image":"Spain.gif","fr_name":"Espagne","es_name":null}, {"it_name":null,"de_name":null,"en_name":"Italy","id":3,"status":1,"image":"Italy.gif","fr_name":"Italie","es_name":null}]


    Pour info, @countries est un array de hashes obtenu par requête MySQL.
  • tarultarul Membre
    11:45 modifié #14
    Bonsoir à  tous,
    Est-ce que isync ou encore ce framework (http://www.zarrastudios.com/ZSync/ZSync.html) ne peuvent pas vous aider pour synchro?
  • yoannyoann Membre
    11:45 modifié #15
    dans 1264190736:

    Bonsoir à  tous,
    Est-ce que isync ou encore ce framework (http://www.zarrastudios.com/ZSync/ZSync.html) ne peuvent pas vous aider pour synchro?


    A voir ce que donne ce Framework, mais les syncservices pour ma part j'ai toujours abandonné au bout de 2 pages de doc et 3 aspirines :-p

    D'autan qu'ici la synchro est entre un serveur sur le net et les iPhone, les syncservices permette de synchro avec un BDD particulière qui est au sein de Mac. C'est pas adapté à  la situation.
  • zoczoc Membre
    11:45 modifié #16
    dans 1264190736:

    Bonsoir à  tous,
    Est-ce que isync ou encore ce framework (http://www.zarrastudios.com/ZSync/ZSync.html) ne peuvent pas vous aider pour synchro?

    Intéressant... Mais comme l'iPhone ne supporte pas nativement les Sync Services, la solution proposée par ce framework implique l'installation d'un daemon sur le Mac, qui fera l'interface avec iSync. L'autre problème avec les Sync Services, c'est qu'ils n'existent pas sur PC, et donc les utiliser risque de mécontenter les utilisateurs d'iPhone et de PC qui ne pourront pas synchroniser leurs données...

  • muqaddarmuqaddar Administrateur
    février 2010 modifié #17
    De retour.

    Comment feriez-vous pour associer des images aux chaà®nes JSON ?

    Pour envoyer l'image, je suppose qu'il est obligatoire de passer par mutableRequest et un postData en plus de la chaà®ne JSON qui ne contient que les données texte ?

    L'idéal aurait peut-être été d'encoder l'image en NSData et pouvoir la passer dans la chaà®ne JSON directement mais je n'aurais pas moyen de la décoder côté serveur.
  • AliGatorAliGator Membre, Modérateur
    11:45 modifié #18
    Alors oui moi je n'utilise le JSON que pour communiquer des données textuelles. Pour les images, j'évite.

    Après, c'est tout à  fait possible de les envoyer en NSData (ou plutôt tu envoies la représentation base64 du NSData retourné par UIImagePNGRepresentation) et de les récupérer côté serveur (décoder le base64 puis enregistrer sur disque directement les octets résultants, dans un fichier avec la bonne extension, et tu as ton image) mais bon.

    Personellement :
    1) Quand mon serveur doit retourner une image à  mon client :
    - soit le client n'attend qu'une image et rien d'autre donc je lui envoie directement (avec le Content-Type qui va bien, genre "image/png") bref comme s'il demandait le fichier image.png au serveur,
    - soit il attend cette image dans la réponse en plus d'autres choses, et dans ce cas je ne lui envoie pas l'image dans la réponse JSON, mais juste l'URL (potentiellement temporaire, plus généralement autogénérée genre "image.php?id=...&w=...&h=..." par ex) à  laquelle il pourra aller récupérer cette image, et je récupère cette image dans un 2e temps via une 2e requête
    2) Quand j'ai besoin que mon client envoie une (ou plusieurs) image au serveur, j'envoie l'image en question en "multipart/form-data", avec une "part" par fichier (bien souvent qu'une seule, mais rien n'empêche de faire transiter plusieurs fichiers d'un coup si tu as besoin).

    Si tu ne connais pas, ce principe de requêtes POST "multipart/form-data" n'est pas bien compliqué. Il suffit d'envoyer une requête POST (comme tu ferais n'importe quelle requête NSURLHTTPRequest) avec un body correctement formatté, ça suit une norme mais qui n'a rien de compliqué et tient en qques lignes.
    C'est d'ailleurs le type de requête et de transfert de contenu typiquement utilisé à  la fois en HTML (quand tu as des formulaires avec un <input type="file" ...>) et pour les mails avec pièce jointe.
  • muqaddarmuqaddar Administrateur
    11:45 modifié #19
    Merci Ali !
    ça confirme ce que je pensais.

    Dans un premier temps, ça sera client => serveur.

    J'ai trouvé cette page pleine d'exemples de formatages de POST data:
    http://www.cocoadev.com/index.pl?HTTPFileUpload
  • AliGatorAliGator Membre, Modérateur
    février 2010 modifié #20
    Yep, c'est tout à  fait ça.

    - Comme tu le vois, quand tu composes ta NSURLRequest tu as juste à  spécifier "multipart/form-data; boundary=MACHIN" (tu mets ce que tu veux comme boundary, MACHIN ou autre chose) comme Content-Type de ta requête, et dans le corps de la requête, tu mets chacune de tes "parts" séparés par "--MACHIN\r\n" (sauf pour après la dernière part où tu mets "--MACHIN--\r\n").
    - Ensuite, chaque "part" consiste ensuite en une ou plusieurs lignes qui correspondent aux headers de cette "part" (au moins le header Content-Disposition, et pour des données qui ne sont pas juste du texte mais par exemple une image ou des données binaires, rajouter le header "Content-Type"), suivi d'une ligne vierge (d'où le "\r\n\r\n" après le dernier header de chaque "part", passer à  la ligne + rajouter une ligne vide) avant d'y mettre le contenu de ladite "part".

    Ce qui donne par exemple un corps de ce genre :
    --MACHIN
    Content-Disposition: form-data; name="realname"

    John Doe
    --MACHIN
    Content-Disposition: form-data; name="email"

    joe.doe[tt][/tt]@company.biz
    --MACHIN
    Content-Disposition: form-data; name="image"; filename="uploadedImage.png"
    Content-Type: image/jpg


    xxxxxx contenu (octets/NSData) du fichier (ici image JPEG) à  uploader xxxxx
    --MACHIN--
    Légende :
    - boundary qui sépare les différentes "parts"
    - headers HTTP de chaque "part"
    - contenu de chaque "part"

    Si tu envoies une requête avec ce corps, de l'autre côté si par exemple tu as du PHP, tu pourras récupérer tes variables avec [tt]$_POST['realname'][/tt], [tt]$_POST['email'][/tt] et [tt]$_FILES['image'][/tt] :)
    A toi d'écrire le code Objective-C pour générer ce genre de trucs en fonction de ce que tu veux envoyer ;)



    PS : Je me demande si le "boundary", même s'il est arbitraire, ne doit pas commencer par un certain nombre de "----", vu que c'est assez courant de voir des boundaries de ce type dans les exemples. Mais je crois que c'est juste une habitude / pratique répandue (d'autant que visuellement si tu affiches le body de la requête que tu envoies tu identifies ainsi facilement les diverses "parts") plus qu'un truc imposé par la norme.
  • muqaddarmuqaddar Administrateur
    11:45 modifié #21
    Ok, super pour ces précisions !

    J'attaque cela très prochainement. ;) Je te tiendrais au courant, j'ai un autre dev à  finir auparavant.
  • muqaddarmuqaddar Administrateur
    juin 2010 modifié #22
    Bonjour,

    Je déterre ce sujet car avec le temps, les choses ont avancé mais se sont complexifiées.

    J'ai longuement réfléchi à  la logique d'une synchronisation client <=> server et je pense pouvoir y arriver. En revanche, là  où ça c'est compliqué, c'est que maintenant cette synchronisation doit être multi-clients, et croyez-moi, je m'arrache les cheveux.

    Pourquoi ? La raison en est simple.

    - J'ai une table SQL sur mon client 1 (iPhone par exemple) avec X vins.
    - J'ai une table SQL sur mon client 2 (iPad par exemple)  avec Y vins.

    Le problème c'est que sur ces 2 bases, des vins différents ont le même ID en clé primaire...

    Sur le serveur où je n'ai qu'une base SQL qui doit tout centraliser (dont les les ID sont bien sûr uniques), j'avais réfléchi à  une parade :

    - je pensais ajouter un champ remote_id dans les tables locales des clients pour avoir l'id du vin en question sur le serveur (ainsi un vin déjà  synchronisé aurait un remote_id dans sa table en local). Cette solution pourrait marcher MAIS les 10 autres tables dépendantes de la première auraient leurs clés étrangères perdues puisqu'elles sont en rapport avec l'id local et non l'id remote...

    Evidemment l'idéal serait d'avoir un ID local unique pour 1 vin donné mais c'est impossible avec plusieurs clients...

    Donc sur ces points, je prends vraiment toute suggestion (en en plus je n'ai pas parlé encore des conflits de version d'un vin...)

  • 11:45 modifié #23
    Tu peux toujours concatener Client_ID et Wine_ID, et si t'es pas convaincu, peut-être qu'un MD5 de la nouvelle chaà®ne pourrait le faire.
  • muqaddarmuqaddar Administrateur
    11:45 modifié #24
    dans 1275416004:

    Tu peux toujours concatener Client_ID et Wine_ID


    Euh... je vois pas en quoi ça résout mon problème. Si tu peux développer...
  • muqaddarmuqaddar Administrateur
    11:45 modifié #25
    J'ai trouvé ça sur un site :

    Before we proceed, we must address the issue of primary keys. All databases support a primary key field for uniquely identifying a record, which is crucial for edit operations as well as relationships between tables. Unfortunately, almost all databases assume management of primary key (PK) fields by default, and don't have any concept of a "distributed" PK space.

    To illustrate, consider two users starting with fresh databases on their iPhones. When each user creates a record, each database will assign a PK of 1 to the records. Now when those users try to sync to the cloud/server, there would be two records with the same PK value (disregarding typical checks for uniqueness, etc.), making a mess of downstream searches, edits, and sync.

    The simple solution is to add an additional "GUID" field to all tables that are to be synchronized, and to generate globally unique identifiers for each new record. Many operating systems and languages have APIs to do just that, generating sufficiently long and random unique ID strings that are statistically unlikely to ever collide.


    L'idée semble très bonne. Toutefois je ne vois toujours pas comment éviter les collisions pour les tables secondaires.
  • AliGatorAliGator Membre, Modérateur
    11:45 modifié #26
    Bah tu peux utiliser un GUID/UUID pour toutes tes PK de toutes tes tables du coup, au lieu des ID AUTOINCREMENT, y compris pour faire tes JOIN, non ?
  • muqaddarmuqaddar Administrateur
    11:45 modifié #27
    dans 1275420257:

    Bah tu peux utiliser un GUID/UUID pour toutes tes PK de toutes tes tables du coup, au lieu des ID AUTOINCREMENT, y compris pour faire tes JOIN, non ?


    Le problème c'est que mes clés étrangères sont actuellement calquées sur les les ID des clés primaires autoincrement des autres tables... Si je dois les calquer sur le nouveau GUID, je dois changer pas mal de code dans mon client, y compris dans mes modèles... ou alors j'ai loupé un truc ?
  • AliGatorAliGator Membre, Modérateur
    11:45 modifié #28
    Ou alors tu jartes ton champ "id" de tes tables (celui qui est AUTOINCREMENT) pour le remplacer par le GUID ?
    Je veux dire, à  la limite renommer ton champ "id" actuel en "autoincrement_id" et créer un nouveau champ "id" pour y mettre ton GUID à  la place.
    Comme ça tu changes pas tes requêtes SQL et ton modèle roby, si ?
  • muqaddarmuqaddar Administrateur
    11:45 modifié #29
    dans 1275432193:

    Ou alors tu jartes ton champ "id" de tes tables (celui qui est AUTOINCREMENT) pour le remplacer par le GUID ?
    Je veux dire, à  la limite renommer ton champ "id" actuel en "autoincrement_id" et créer un nouveau champ "id" pour y mettre ton GUID à  la place.
    Comme ça tu changes pas tes requêtes SQL et ton modèle roby, si ?


    ça implique de mettre à  jour toutes les tables dépendantes de la principale avec le GUID en clé secondaire il me semble ?

    En fait, le fond du problème c'est le fait que id soit autoincrément dans 2 bases différentes. C'est clair que le GUID s'il est dans un espace indéfini et unique sur X clients peut le faire. Effectivement, la solution la plus simple est peut-être de tout simplement passer l'id en mode GUID (en virant l'autoincrement) et forcément donc mettre à  jour les clés secondaires des autres tables...
  • muqaddarmuqaddar Administrateur
    juin 2010 modifié #30
    Voilà  une catégorie NSString pour générer un UUID en Cocoa (glanée sur le net et adaptée) :

    #import &quot;NSString+UUID.h&quot;<br /><br />@implementation NSString (UUIDCategory)<br /><br />+ (NSString*)stringWithUUID <br />{<br />	// create a new UUID<br />	CFUUIDRef uuidObj = CFUUIDCreate(nil);<br />	<br />	// get the UUID string representation<br />	NSString *uuidString = (NSString*)CFUUIDCreateString(nil, uuidObj);<br />	CFRelease(uuidObj);<br />	return [uuidString autorelease];<br />}<br /><br />@end
    


    ça peut intéresser du monde.

    Ce qui donne par exemple : 1011BCA7-7C19-446B-9F42-165103E11AB1
  • AliGatorAliGator Membre, Modérateur
    11:45 modifié #31
    Je l'utilise déjà  depuis quelques temps et comptait justement publier une catégorie sur mon repo GitHub Ali-Cocoa-Classes.

    L'idée est d'avoir des catégories qui rajoutent :
    - La génération d'un UUID dans NSString (= ton code)
    - Le calcul d'un MD5 d'un buffer/NSData (via CommonCrypto/CommonDigest.h et CC_MD5). Et tant qu'à  faire faire aussi SHA-1 & co qui sont aussi dispos dans CommonCrypto
    - Une méthode de commodité qui fait la mm chose sur une NSString (récupère la représentation data UTF8 de la string, demande le MD5)
    - Une méthode de NSData qui affiche la représentation hexa d'un buffer, avec caractère séparateur optionnel tous les N octets
Connectez-vous ou Inscrivez-vous pour répondre.