Whaooo, un peu perdu, version 2.0!

tabliertablier Membre
Je n'ai pas utilisé jusqu'à  présent les spécificités d'Objective- 2.0. J'essaie de m'y plonger!  Je dois dire que @property, ....., @Assign, .... etc ça n'est pas évident pour moi. J'ai lu les grandes discutions sur le sujet (entre Psycho13, Schlum ......). A part raccourcir le nombre de lignes à  écrire, je vois pas vraiment! le langage devient carrément symbolique!
Quite à  être ésotérique, on devrait tous se mettre à  AppleScript!!

Réponses

  • laudemalaudema Membre
    23:29 modifié #2
    dans 1285014737:

    A part raccourcir le nombre de lignes à  écrire, je vois pas vraiment! le langage devient carrément symbolique!
    Quite à  être ésotérique, on devrait tous se mettre à  AppleScript!!

    Pour les nouveaux venus c'est quand même bien de ne pas avoir à  écrire les différentes méthodes et Apple visait probablement ceux là .
    C'est automatique mais en plus "atomic" pour être "thread safe" sans avoir à  s'en préoccuper.
    ça renseigne: tu sais si ce que tu reçois est retenu ou copié ou simplement retourné.

    Et il n'y a pas que ça:
    - La "dot.syntax", plus lisible que les []imbriqués et surtout vérifié par le compilateur.
    - Le garbage collector qui peut faciliter grandement la vie.
    - Les Blocks pour rajouter une fonction là  où tu en as besoin.
    - La boucle for (elements in tableau) pour parcourir rapidement et simplement une collection.

    Tout ça me semble très utile au quotidien et il me serait plus difficile de m'en passer qu'il ne te sera de l'adopter ;)
  • AliGatorAliGator Membre, Modérateur
    23:29 modifié #3
    Oui même si les blocks sont arrivés un peu plus tard qu'Objective-C 2.0 je m'y suis essayé un peu et j'adore, c'est une tuerie, bien pratique quand on se met dans le principe que certains autres mécanismes surtout pour les actions asynchrones (callbacks, etc).
    Sinon en effet laudema a cité d'autres trucs de ObjC2.0 mais il y en a encore, je pense entre autres enfin à  l'apparition des mots clés @optional/@required qu'on peut utiliser dans la déclaration des @protocol, ce qui permet dorénavant de se passer totalement des protocoles informels (implémentés sous forme de catégories de NSObject mais qui avaient de nombreux inconvénients, en particulier le fait d'être informels et de ne pas du tout être vérifiés à  la compilation...)
  • laudemalaudema Membre
    23:29 modifié #4
    Il y a probablement encore deux ou trois choses qui n'auront pas été évoquées (Grand Central Dispatch par exemple que je n'ai pas eu l'occasion d'utiliser) mais une bien agréable que j'avais oubliée c'est la notion d' Extension de Classe

    http://developer.apple.com/library/ios/documentation/cocoa/Conceptual/ObjectiveC/Articles/ocCategories.html#//apple_ref/doc/uid/TP30001163-CH20-SW2
    une catégorie sans nom MaClasse() permet de rajouter des méthodes "privées" à  une classe dans un header en tête de l'implémentation.

    Alors, comment trouves tu la 2.0 ?
  • tabliertablier Membre
    23:29 modifié #5
    une catégorie sans nom MaClasse() permet de rajouter des méthodes "privées"
    ça, c'est la seule chose que j'utilise couramment. Pour le reste, l'utilisation ne m'est pas naturelle et il y a bien des choses que je n'ai pas intégré. Une bonne explication avec exemple me rendrait vraiment service. Et si possible en français, car ma compréhension est bien meilleure dans ma langue maternelle.
    Bon il ne me reste plus qu'à  faire ce que j'ai dit à  "fab":  je lis, j'essaie, je me plante, je recommence et enfin je sais!
  • AliGatorAliGator Membre, Modérateur
    23:29 modifié #6
    Bah même si tu le vois pas quand tu ne fais qu'utiliser les @protocoles, rien que l'existence des @optional ça change vraiment tout. Tu le vois encore plus quand tu crées tes propres @protocols en plus d'utiliser ceux d'Apple genre UITableViewDelegate ou autre.

    Les Fast Enumerations (boucles for sur les collections genre [tt]for(NSString* str in monTableauDeChaines) {...}[/tt] dont parlait laudema) sont également très utiles (et en plus optimisées), la dot-syntax (notation pointée) on prend également vite l'habitude surtout quand on met des @property un peu partout dans now classes... par exemple c'est quand même plus sympa (et plus naturel du moins perso je trouve après chacun ses goûts et choix) d'écrire [tt]viewctrl.view.backgroundColor = clr[/tt] plutôt que [tt][[viewctrl view] setBackgroundColor:clr];[/tt]...
  • tabliertablier Membre
    23:29 modifié #7
    UIxxxx je n'utilise pas. Ce doit être dans dev iPhone/iPad et je ne développe pas pour ces machines.
    Je n'ai jamais créer de protocole. J'en ai utilisé un ou deux explicitement, rien de plus (et bien sur, certaines classes sont conformes à  certains protocoles).
    Les "delegates", j'utilise comme tout le monde.
    Les "fast énumérations": je connais, en AppleScript ça existe depuis l'origine, c'est pas une nouveauté.
    Si j'écris "viewctrl.view.backgroundColor = clr" j'ai l'impression de faire du VisualBasic. Pour ma part, la syntaxe entre crochets ne me dérange pas, ce n'est que de la syntaxe et on s'y fait.
    DONC: il doit y avoir des avantages cachés si vous êtes si enthousiastes.
    De toute façon, il faudra bien que je m'y fasse!!!

  • 23:29 modifié #8
    dans 1285091295:

    UIxxxx je n'utilise pas. Ce doit être dans dev iPhone/iPad et je ne développe pas pour ces machines.
    Je n'ai jamais créer de protocole. J'en ai utilisé un ou deux explicitement, rien de plus (et bien sur, certaines classes sont conformes à  certains protocoles).
    Les "delegates", j'utilise comme tout le monde.
    Les "fast énumérations": je connais, en AppleScript ça existe depuis l'origine, c'est pas une nouveauté.
    Si j'écris "viewctrl.view.backgroundColor = clr" j'ai l'impression de faire du VisualBasic. Pour ma part, la syntaxe entre crochets ne me dérange pas, ce n'est que de la syntaxe et on s'y fait.
    DONC: il doit y avoir des avantages cachés si vous êtes si enthousiastes.
    De toute façon, il faudra bien que je m'y fasse!!!


    Je suis d'accord avec toi sur l'histoire des "dot". ça m'embête et pourtant je les utilise de temps à  autre. Malgré tout, je trouve ça beaucoup plus clair avec des crochets. J'utilise surtout les dot pour récupérer la frame d'une vue par exemple...
    En revanche, le gros avantage des @property c'est, pour moi, d'éviter l'implémentation du getter/setter. ça simplifie grandement le code et ça évite parfois des erreurs humaines toutes bêtes. Comme tu l'as dit, il n'y effectivement pas vraiment d'autre avantages.. mise à  part le système de "dotation" (si on peut appeler ça un avantage)
  • AliGatorAliGator Membre, Modérateur
    23:29 modifié #9
    Il faut aussi savoir que même si ObjC 2.0 apporte toutes ces nouveautés :
    - Tu t'y feras sans doute (ou pas) au fur et à  mesure, ce sont les genre de choses dont on voit les bénéfices qu'en utilisant, c'est pas forcément expliquable
    - Et surtout comme ça dépend des goûts, rien ne t'oblige à  utiliser tout ça. Même si la notation pointée existe, tu peux toujours utiliser les crochets de partout. Même si les FastEnumerations existent, tu peux toujours utiliser les boucles à  index (moins rapides/optimisées ceci dit car récupèrent les objets un par un).
    - Bon après pour les @protocols avoir le @optional ça se voit pas pour toi si tu ne crées pas tes propores protocoles, mais l'avantage est réel (en fait c'était un réel manque dans ObjC 1.0 qui a été contourné par l'utilisation des catégories pour implémenter les "protocoles informels" mais c'était de la bidouille et se basait sur le fait que le développeur devait respecter proprement les règles, car s'il faisait un écart le compilateur n'aurait mentionné aucune erreur alors que ça aurait planté ou ça n'aurait pas marché...
    - Et pour les blocks (que tu connais sans doute déjà  un peu si tu connais les "closures" en Javascript par exemple) ça apporte un réel avantage de lisibilité (et de design pattern et d'architecture logicielle) quand on les utilise... mais encore faut-il avoir l'utilité de les utiliser (par exemple Grand Central Dispatch ne pourrait exister dans les blocks, les animations (sur iPhone mais ça sera bientôt pareil sur Mac si c'est pas déjà  le cas) qui se font avec les blocks sont bien plus lisibles dans le code et évitent d'avoir des méthodes éparpillées de partout pour gérer les différents stades de l'animation (là  tout se code au même endroit on n'a pas à  avoir des didEndSelector & co). Pareil d'ailleurs sur Mac pour les NSOpenPanel & co ce sont des patterns permettant une bien plus grande lisibilité du code en regroupant toute la mécanique au même endroit dans le code plutôt que d'avoir des méthodes de partout risquant même d'être appelé par plusieurs NSOpenPanel & co et nécessitant de faire des tests pour savoir duquel il s'agit...

    Mais bon, ça encore ça se réalise en pratique. Comme c'est très utilisé dans GCD ou que c'est assez utile sur iPhone (surtout moi qui fait de gros projets et soigne toujours mon archi logicielle avant) on réalise plus facilement avec un réel projet et une réelle problématique.
  • AliGatorAliGator Membre, Modérateur
    23:29 modifié #10
    Exemple type pour les blocks : dans une application j'ai dû implémenter un mécanisme de cache des images.

    Sans les blocks, j'aurais utilisé NSURLConnection et implémenté le protocole NSURLConnectionDelegate (tiens, encore un protocole informel qui a résisté à  l'envahisseur, mais qui ne va pas tarder à  être converti en un protocole formel histoire de faire propre et que le compilateur puisse remonter les erreurs le cas échéant) pour télécharger mon image... et ensuite, une fois l'image téléchargée ? Je notifie un objet que j'ai mis comme delegate, en appelant une méthode pour le prévenir ? Ok, pourquoi pas... mais dans des cas comme un écran contenant une table/liste et où je vais télécharger plein d'images, comment savoir pour quelle image la méthode de delegate est appellée ?
    Ca donnerait un truc comme ça à  l'usage :
    // commande le download et informe le delegate quand c&#39;est fini<br />... {<br />&nbsp; [[ImageDownloader sharedDownloader] downloadImageAtURL:url1 delegate:self];<br />&nbsp; [[ImageDownloader sharedDownloader] downloadImageAtURL:url2 delegate:self];<br />&nbsp; [[ImageDownloader sharedDownloader] downloadImageAtURL:url3 delegate:self];<br />&nbsp; [[ImageDownloader sharedDownloader] downloadImageAtURL:url4 delegate:self];<br />}<br /><br />-(void)imageDownloader:(ImageDownloader*)dl didFinishDownloadingImage:(NSImage*)image forURL:(NSURL*)url {<br />&nbsp;  ... le code pour faire ce qu&#39;on veut avec l&#39;image enfin récupérée de façon asynchrone<br />&nbsp; if ([[url absoluteString] isEqualToString:url1]) {<br />&nbsp; &nbsp; imageView1.image = image;<br />&nbsp; }<br />&nbsp; if ([[url absoluteString] isEqualToString:url2]) {<br />&nbsp; &nbsp; imageView2.image = image;<br />&nbsp; }<br />&nbsp; if ([[url absoluteString] isEqualToString:url3]) {<br />&nbsp; &nbsp; imageView3.image = image;<br />&nbsp; }<br />&nbsp; if ([[url absoluteString] isEqualToString:url4]) {<br />&nbsp; &nbsp; imageView4.image = image;<br />&nbsp; }<br />&nbsp; ...<br />}
    
    Sauf que dans le code de "imageDownloader: didFinishDownloadingImage: forURL:" il te faudrait ensuite tester pour savoir de quelle URL il s'agit pour savoir quelle NSImageView mettre à  jour avec cette image par exemple... comment savoir ? Faut garder la liste des associations entre les URLs et les NSImageViews ? Et encore j'ai pris un exemple simple, si la vue change en cours de route c'est encore le boxon (et sur iPhone avec les UITableViews qui recyclent leurs cellules au fur et à  mesure que tu scrolles pour éviter de gaspiller la mémoire, c'est pire). Le gros problème dans ce cas est que tu es obligé de garder une référence vers tes URLs pour savoir à  quelle imageView elle est associée, pour que quand l'image est enfin téléchargée et disponible (download asynchrone) tu sache dans quel imageView la mettre

    Avec les blocks, mon code ressemble à  ça à  la place :
    [[ImageDownloader sharedDownloader] loadImageForUrl:url1 competion:^(NSImage* img) { imageView1.image = img; }];<br />[[ImageDownloader sharedDownloader] loadImageForUrl:url2 competion:^(NSImage* img) { imageView2.image = img; }];<br />[[ImageDownloader sharedDownloader] loadImageForUrl:url3 competion:^(NSImage* img) { imageView3.image = img; }];<br />[[ImageDownloader sharedDownloader] loadImageForUrl:url4 competion:^(NSImage* img) { imageView4.image = img; }];
    
    Et du coup nul besoin d'avoir une variable d'instance qui garde les associations entre les URLs et les ImageViews comme dans le premier cas.


    Bon ce n'est qu'un exemple (et puis pour cet exemple simpliste j'aurais pu faire autrement côté design, en réalité ma problématique est plus compliqué et mon cache est partagé etc) il en existe d'autre, mais au moins ça a le mérite de te montrer un exemple concret.


    Les autres exemples concrets tu pourras en trouver dans les tutos sur GCD, où par exemple grace aux blocks tu peux exécuter des boucles parallèles, donc faire du multithreading, comme si de rien n'était, avec un code qui a le même look qu'une boucle "for" classique, sauf que tout est parallélisé, et ce sans avoir à  gérer les NSThreads, les mutex, le passage de paramètres entre les threads et le mail thread, la synchro et tout le bastringue.
  • AliGatorAliGator Membre, Modérateur
    septembre 2010 modifié #11
    Ah si une grosse différence : avec Objective-C 2.0 vient un nouveau runtime.
    Avant Objective-C 1.0 utilisait ce qu'on appelle maintenant le "Legacy Runtime" (le "Runtime historique" si vous voulez). Maintenant avec Objective-C 2.0 c'est le "modern runtime" (ils l'appellent comme ça) qui est utilisé.

    Et une des grandes différences (entre autres) entre le legacy runtime et le modern runtime, c'est que dans le modern runtime, il n'y a plus besoin de prévoir des backing variables pour les @property (autrement dit plus besoin de prévoir des variables d'instance associées aux @property pour les @synthetiser).

    Un exemple vaut mieux qu'un long discours
    @interface Toto : NSObject {<br />&nbsp; // aucune variable d&#39;instance<br />}<br />@property(nonatomic, retain) NSString* totoProp;<br />@end
    
    @implementation Toto<br />@synthesize totoProp; // pas de variable d&#39;instance du même nom ? pas grave avec le modern runtime !<br />@end
    


    Quand on commence à  avoir un sacré paquet de propriétés, ça devient très pratique.

    Bon ceci dit j'avoue que je n'utilise pas beaucoup cette possibilité... mais en fait plutôt par habitude de déclarer mes ivars en fait, j'ai pas perdu mes habitudes du 1.0 pourtant ça condenserait un peu mon code parfois :P
Connectez-vous ou Inscrivez-vous pour répondre.