Propriétés sans iVars ?
Neofelis
Membre
Bonjour,
Je suis tombé sur ce lien avec un post très intéressant d'Ali http://pommedev.mediabox.fr/frameworks-communs-objective-c/(tutocours)-variables-d'instance-proprietes-et-accesseurs/
J'ai bien compris qu'une propriété n'était pas forcément lié à une variable d'instance si les accesseurs ne sont pas créés automatiquement.
Mais je viens de faire un test surprenant : J'ai créé une propriété basique (contenant un BOOL ou un NSString par exemple) et j'ai généré automatiquement mes accesseurs avec @synthesize. En supprimant la déclaration de ma variable d'instance j'ai constaté que tout fonctionnait parfaitement. Mon getter et setter continuait de récupérer et stocker mes valeurs. Comment est-ce possible ? Où est stockée la valeur dans mon setter si aucune variable d'instance n'est déclarée et que je ne fournis à mes accesseurs aucun mécanisme de stockage ? J'en viens à me demander si déclarer une iVar est utile lorsque l'on déclare une propriété ???
Je suis tombé sur ce lien avec un post très intéressant d'Ali http://pommedev.mediabox.fr/frameworks-communs-objective-c/(tutocours)-variables-d'instance-proprietes-et-accesseurs/
J'ai bien compris qu'une propriété n'était pas forcément lié à une variable d'instance si les accesseurs ne sont pas créés automatiquement.
Mais je viens de faire un test surprenant : J'ai créé une propriété basique (contenant un BOOL ou un NSString par exemple) et j'ai généré automatiquement mes accesseurs avec @synthesize. En supprimant la déclaration de ma variable d'instance j'ai constaté que tout fonctionnait parfaitement. Mon getter et setter continuait de récupérer et stocker mes valeurs. Comment est-ce possible ? Où est stockée la valeur dans mon setter si aucune variable d'instance n'est déclarée et que je ne fournis à mes accesseurs aucun mécanisme de stockage ? J'en viens à me demander si déclarer une iVar est utile lorsque l'on déclare une propriété ???
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Oui.
En tout cas, ça fait du bien d'avoir quelques nouveaux qui aiment comprendre la tambouille. Et ça mérite d'être souligné.
Tu compiles en 32 ou 64 bits ? Mets-toi en 32 bits only et normalement tu auras un message d'erreur.
Tout à fait d'accord même si, moi-même, je n'ai pas creusé la question
Effectivement ! Est-ce un bug ? Y'a-t-il un moyen d'avoir toutes les erreurs attendues en 64 bits ? ^^
Interfaçage en 32 bits :
Interfaçage en 64 bits :
Non, c'est une fonctionnaité du "modern runtime", disponible pour les applications Mac 64 bits et les applications iOS à partir de la version 4.
Tous les détails sont dans la documentation officielle concernant le runtime objective-c
En effet, il existe deux Runtimes : le "Legacy Runtime" (traduisez "Runtime Historique") qui nécessite de déclarer les ivar, et le "Modern Runtime" (traduisez... bah devinez ^^) qui permet de se passer de la déclaration de la ivar, le @synthesize sachant la générer automatiquement.
Après, c'est vrai qu'il se trouve que sous MacOSX 32 bits, c'est le Legacy Runtime qui est encore utilisé, et sous MacOSX 64 bits, c'est le Modern Runtime qui est utilisé. Et sous iOS ça a toujours été le Modern Runtime.
Tout est expliqué ici dans la doc (et tu as aussi un lien, dans ce paragraphe, vers l'article Runtime Versions and Platforms qui indique quels runtimes sont utilisés suivant la plateforme)
Tu as devancé ma question pour iOS.
Vu le nombre de classes modèles que j'ai multiplié par le nombre de iVars, ça donne envie de s'y mettre...
Bon, ça veut dire que je coupe le pont avec iOS 3.2... mais pourquoi pas ?
EDIT:
Ali a répondu à ma question... adieu les déclarations d'iVar sur iOS alors...
Coquille dans la doc ou réalité ?
En tout cas moi j'omet de plus en plus les ivars, surtout quand je veux faire une interface de classe (.h) plus propre et lisible en n'exposant que les @property. Par exemple pour ma classe OHAttributedLabel sur github j'ai supprimé toutes les backing variables de mon .h.
C'est vrai que j'ai encore un peu de mal avec la doc, elle est tellement complète (et c'est une qualité) que je ne sais parfois pas où chercher alors que mes réponses se trouvent dans 99% des cas dedans ^^
Je viens de faire un test sans soucis en compilant pour iOS 3.2.
J'avais remarqué ça en bidouillant, il y a néanmoins un gros problème lié à cette pratique, le débuggueur n'affiche que les ivars déclarées dans le .h. Donc si tu veux inspecter tes ivars en mode debug ça semble râpé... A moins qu'il y ait une astuce pour inspecter les ivars dans le débuggueur même si elles ne sont pas déclarées dans le .h ?
Sil le fait par contre je ne sais pas quelle variable tu pourrais lire, peut être y en aura t'il une du même nom que la @property correspondante ?
Bref c'est loin d'être gênant pour moi de ne pas voir dans le débogueur les backing variables associées à mes @properties. Après tout, si je ne les crée pas moi-même, c'est pour ne pas m'en soucier, et ne voir cela comme des propriétés (gérées de façon autonomes) et pas des accesseurs à une ivar donnée (que j'aurais définie)
ça ne m'étonne pas de toi
J'ai oublié de préciser qu'il fallait aussi cocher la petite case à droite, la colonne avec la flèche => pour avoir le plaisir de suivre l'évolution du code dans la console sans que l'appli s'arrête à la ligne indiquée..
Mais le débugeur sait tout à fait se débrouiller tout seul pour afficher les ivars, pourquoi tu dis ça ?
On parle de propriétés opaques sans backing variables dans ce thread justement, donc ce ne sont pas des variables, mais bien des propriétés. Et comme une propriété peut être transciente et voir sa valeur calculée (voir les messages que j'ai fait sur le forum sur les @properties) et non pas juste issue d'une variable d'instance, encore heureux que le compilateur ne cherche pas à afficher sa valeur à chaque fois dans le débogueur si on lui demande pas !
Autant pour moi, je crois que je me suis un peu emmêlé le vocabulaire
En gros ce que je veux dire c'est : si j'ai la classe MaClasse suivante :
Quand je vais vouloir par exemple faire du pas à pas en mode debug sur maMethode, dans le petit triangle >self , il n'y aura pas maVariable. Par contre, si j'avais déclarée maVariable elle aurait été disponible directement dans le debugger :
Dans la première situation il va falloir utiliser les commandes du debugger, mais pas dans la deuxième...
Autre exemple, en prenant des noms différents et plus explicites pour bien saisir le vocabulaire :
Ici dans le débogueur tu ne verras que maVar1. Tu ne verras pas maProp2 ni maProp3... ni maProp1 en fait (tu verras maVar1 et il se trouve que maProp1 se base sur cette variable d'instance pour stocker sa valeur, mais bon ça reste la variable que tu vois, pas la propriété).
Et autant on peut comprendre qu'on aimerait pouvoir voir maProp1 et maProp2 dans le débogueur... mais si tu regardes le cas de maProp3 tu comprends que pour ce cas ce n'est pas trop possible simplement : faudrait que le débogueur exécute le code du getter pour afficher la variable, et ça tu n'as peut-être pas envie qu'il le fasse si tu ne le demandes pas explicitement.
Genre dans mon exemple ça va encore, mais si j'avais à la place fait une requête réseau pour demander la valeur à un WebService avant de la retourner... hum !
Bon après ok à la limite s'il détectais que le code de la @property avait été compilée/générée automatiquement via un @synthesize et pas manuellement via du code "perso", et seulement dans ce cas affichait la valeur de ladite @property à côté de la liste des variables, ça pourrait être sympa.
Mais faut garder à l'esprit que ça reste des "propriétés" et pas des "variables".
Certes on confond parfois les deux car on a pris l'habitude qu'il y ait une variable d'instance d'associée à nos @property, justement avec le Modern Runtime ce n'est plus vrai (ou bien c'est vrai mais cette ivar est créée à la volée par le compilateur -- Dieu sait quel nom le compilo lui donne d'ailleurs à cette variable en interne -- et est masquée du code). Or on n'a toujours vu que les variables dans cette fenêtre en haut du compilateur, jamais les propriétés.