[Résolu] Variable statique "dupliquée"
Contexte :
- j'ai une classe myClass qui contient une variable count déclarée en static dans le .m (qui me sert à dénombrer certaines instances de la classe)
- il y a une méthode de classe getCount qui me permet de récupérer la valeur de count
- et diverses méthodes de classe et d'instance qui agissent sur count
Jusqu'à présent je n'avais jamais eu de souci avec ce genre de construction.
Et là je me suis aperçu que [myClass getCount] et [[aClassInstance class] getCount] ne donnent pas le même résultat.
Tout se passe comme si ma variable static count était dupliquée, ce que j'ai pu vérifier sous debugger ; suivant comment j'y accède je n'ai pas la même valeur d'adresse.
Quelqu'un a une idée ?
Petites précisions (je ne sais pas si ça joue) :
- myClass hérite de NSManagedObject
- count est utilisée et mise à jour dans des blocks
Réponses
Je pensais avoir déjà assez répété que les variables globales, c'est le mal, et le meilleur moyen d'avoir des prises de têtes en cas de problème pour débuguer, que ce soit pour du threading ou pour retrouver leur contexte et à quelle(s) Compilation(s) Unit(s) ils appartiennent.
Typiquement j'ai pas lu jusqu'au bout (car dès que je vois "variable globale" je cherche pas plus loin je m'arrête de lire normalement, mais c'est loin de m'étonner que tu aies des problèmes, je l'ai déjà assez dit pourtant
Et comment fait-on pour simuler des propriétés de classe alors ?
2) Ou alors on utilise les associated objects du runtime
3) Ou alors on passe à Swift, qui supporte ce concept (ce qui n'empêche pas que ça reste tout de même une mauvaise idée si ce n'est pas bien proprement protégé contre les accès concurrents)
Ma variable n'est utilisée que par trois méthodes (toutes de classe, la seule méthode d'instance qui l'utilisait contient maintenant un appel à une méthode de classe). L'exécution de ces méthodes est forcée sur la queue principale car la valeur doit être affichée. Je pensais que ça suffisait dans ce cas simple pour ne pas avoir d'ennuis avec les accès concurrents.
Je vais utiliser une sharedInstance.
Merci
Et établir pour chaque objet une relationship avec un objet unique qui contiendrait la valeur?
J'aime bien le non sens d'Ali...
"Les globals c'est le mal" --> On a pas parler de global mais de static, rien n'indique que la static n'est pas déclarée dans une méthode.
"utilise une shared instance" --> très drôle vu que les shared instance ont besoin de ces static ^^
Jean-Pierre, est-ce que tu peux nous donner un aperçu du code ?
Quand en plus JP ajoute "la variable est utilisée par 3 méthodes" ça sous-entend de plus qu'elle est accessible par plusieurs méthodes (et c'est tout le problème des globales non protégées contre les accès concurrents) et donc bien globale et pas déclarée à l'intérieur d'une méthode avec un accès protégé et contrôlé comme dans une sharedInstance.
Donc je ne vois pas trop le non-sens yoann puisque ma proposition initiale est de dire "don't do this", et que ma proposition d'utilisation des sharedInstance est finalement "si tu as vraiment besoin de le faire au moins restreint l'accès de cette static uniquement à une seule méthode qui en contrôlera l'accès, et protège cet accès contre les accès concurrents en multi-threading via l'utilisation d'un mécanisme tel qu'un dispatch_once et une exposition de la variable en read-only de l'extérieur" " autrement dit ce qu'on appelle communément en bien plus court que cette longue phrase... une sharedInstance.
Bon ben en fait, je ne suis pas plus avancé.
Avec une sharedInstance ça ne marche toujours pas. J'ai toujours une variable static qui est dupliquée, et je me retrouve avec DEUX sharedInstance. Et même le verrou du dispatch_once est dupliqué (logique, sinon je n'aurais pas 2 instances).
Tout se passe comme si j'avais du code dupliqué (et pas seulement le code manifestement). Je continue à chercher du côté du build, ou de ces trucs là .
ça n'est jamais arrivé à quelqu'un ce genre de chose ?
ça arrive aussi quand tu as ta classe dans deux bundles de code chargés séparément. Ce qui arrive si tu es dans du code de tests unitaires et que ton application est le TEST_HOST de ton bundle de test U, et que tu as mis ta classe dans les 2 target (j'ai écrit un article là dessus dans le wiki de OHHTTPStubs, j'en ai déjà parlé ici)
Ou quand tu développes des plugins pour OSX via l'architecture faite pour dans AppKit via les NSBundle (ce qui fondamentalement est ce qui est utilisé quand tu lances des tests U via un TEST_HOST finalement).
Dans tous les cas ceci résulte en deux instances distinctes de la meta-classe chargée en mémoire (puisque ce sont deux images binaires distinctes chargées au runtime en même temps) donc deux fois la même classe dans ton runtime. Tout ça parce que ton architecture de projet (structure de targets et de répartition des classes communes dans des targets dédiés etc) n'est pas cohérente.
Tant qu'il n'en sait pas plus sur la topologie de ton projet ça va être dur de jouer aux devinettes ;-)
YESSSS !
J'étais sur la même piste en farfouillant les logs système ; j'ai effectivement certaines classes chargées deux fois.
Et c'est effectivement à cause d'une target de test qui initialement était standalone. Je n'ai pas pensé à vérifier les attachements des codes source aux targets quand j'ai changé le TEST_HOST.
J'ai eu la flemme de définir une nouvelle target pour une dizaine de tests ; ça m'apprendra de faire le flemmard.
Bon ben Merci encore
Bravo, ça avait l'air bien relou comme problème !