Stockages d'informations
Bonjour à tous,
Mon premier post sur ce forum, et j'ai beaucoup d'interrogations concernant la programmation sur iOS.
J'ai commencé il y a 2 mois avec le livre de Big Nerd Ranch, Objective-C puis Programmation iOS. Je pense avoir compris pas mal de choses sur la logique de développement et sur le langage en lui même, mais j'ai pas mal d'interrogations sur certains points, tout d'abord sur la sauvegarde de données.
Je développe pour prendre mes marques un petit jeu très simple, où des personnages défilant de gauche à droite doivent être assommés par des oeufs qui leurs tombent dessus. A terme, nous aurons plus de cinquante personnages différents, qu'il faut stocker quelque part pour gérer la génération aléatoire des personnages. Jusqu'à maintenant, le chargement des images se fait dans le ViewDidLoad, mais j'aimerais stocker tout ça dans une BDD et charger des personnages à chaque fois qu'il en faut.
Ainsi, comment puis-je sauvegarder tout un tas d'informations et d'images pour les utiliser quand je veux ?
J'ai lu pas mal de choses à propos de CoreData sur ce forum et SQLite ailleurs, mais les 3/4 des articles ou tuto parlent de récupérer des données sur le net avec NSData, ce qui n'est pas du tout ce que je souhaite finalement.
Qu'en pensez-vous ? Merci d'avance !
Réponses
Salut Gumify !
Bienvenue !
Voici le conseil que je te donne :
- tu vas créer un classe Perso, qui prend en argument une image (et d'autres paramètres)
- cette classe pourra te créer autant de perso que tu veux !
- du coup, tu n'auras pas besoin de les loader dans viewDidLoad, ils seront créés lorsque tu appelleras la méthode qui crée un personnage.
Ton problème, j'ai l'impression, est moins un problème de stockage que de bien comprendre la programmation orienté objet et la gestion de la mémoire (@properties strong, weak).
J'ai un peu le même problème que toi ; je dois créer une base de données initiale qui contient des fichiers (ce ne sont pas des images mais ça ne change rien au problème).
J'ai créé dans mon projet une nouvelle Target "BuildDatabase" de type test. Là dedans j'ai mis le code qui permet de créer une base de données vide et de la peupler, et j'y ai associé aussi tous mes fichiers à intégrer dans la base de données (ce sont des ressources attachées à la target).
Chaque fois que je modifie la structure de la base de données, ou bien le contenu initial, j'active le "test" BuildDatabase pour créer mon fichier initial SQLite que je copie dans les ressources de l'application.
@Colas2 Merci pour tes suggestions !
J'ai déjà fait une classe Personnage qui prend en paramètre le nom de l'image et ses dimensions, qui me place le bonhomme et ainsi de suite, ça marche nickel ! Donc pour le moment, j'ai mis dans un NSArray les noms d'images et leurs dimensions. Mais je suis obligé moi-même de remplir le tableau au viewDidLoad, c'est à dire que je rempli moi même le tableau dans le code, puis j'affiche ! Or, je ne sais pas si cela est mieux ou pas, mais j'avais pensé stocker ces noms et dimensions etc. dans une BDD de manière à ne pas charger cela écrire cela moi même (ou dans le cas d'une Maj avec plus de perso, de devoir les ajouter dans mon NSArray de base).
Suis-je dans la bonne direction avec mon NSArray que je charge "manuellement" dans le ViewDidLoad ou j'ai loupé quelque chose ?
@jpimbert Ah bien vu ! Et d'ailleurs, l'implémentation d'une solution comme ça est-elle compliquée ?
Je pense rester dans la simplicité en modifiant comme il faut ma classe personnage, mais sinon j'adopterai sûrement la seconde solution !
Merci à vous deux en tout cas!
Du coup dans ton viewDidLoad tu peux faire un [NSArray arrayWithContentsOfFile:cheminDeTonPlist], itérer sur chaque élément de ton tableau (donc sur chaque NSDictionary*) puis créer chaque objet Personnage à partir de ce dictionnary (quitte à prévoir une méthode "initWithDictionary:" sur ta classe Personnage). Ca t'évitera d'écrire en dur dans ton code tous tes personnages.
D'accord très bien, merci !
Si jamais je garde l'écriture en dur dans mon code, est-ce que cela alourdi le programme du fait de charger à chaque lancement le tableau, où il n'y a aucun inconvénient à garder cette méthode ?
De plus, pour faire bouger les personnages, j'ai utilisé des NSTimers, avec CGPointMake, en leur donnant une nouvelle position calculée relativement à chaque exécution du timer. Est-ce une solution correcte au niveau des ressources où il vaut mieux préviligier une autre solution qui pourrait peut-être être moins gourmande en ressources ?
Et au niveau du chargement des images, je les charges sur un coté invisible de l'écran, puis les fait défiler. Faut-il réaliser le chargement de l'image sur un thread à part ou il n'y a pas d'inconvénient à tout garder sur le main thread ?
Merci pour vos réponses, j'y vois déjà beaucoup plus clair !!!
Alors non ce n'est pas une bonne façon de faire. Déjà , si tu tiens vraiment à faire une animation à la main, à bouger les éléments frame par frame, utilise plutôt un CADisplayLink qu'un NSTimer. Sur le principe c'est globalement pareil sauf que là où NSTimer se déclenche toutes les N secondes que tu as précisé, CADisplayLink est couplé au taux de rafraà®chissement de ton affichage et va donc appeler ton code de déplacement des personnages à une fréquence en phase avec le rafraà®chissement de ton écran.
Cependant, je te conseille plutôt de te tourner vers CoreAnimation. Soit avec les CAAnimation, mais ça c'est si vraiment t'avais des animations complexes avec des chemins pas linéaires et tout, pas la peine de sortir la grande artillerie pour ça, soit donc pour faire beeeauucoup plus simple, avec [UIView animateWithDuration:animations:] et en affectant directement la frame de ton personnage à sa destination dans le block d'animation, et tu laisses iOS faire l'animation de la position d'origine à la position finale tout seul.
De toute façon tu n'as pas le choix : tout ce qui est relatif à l'interface graphique doit se faire O-BLI-GA-TOI-RE-MENT dans le MainThread (d'ailleurs ce n'est pas vrai qu'en ObjC). Tout ce qui est afférant à l'UI doit être fait dans le maintThread (sinon crash assuré). Car c'est le mainThread qui fait le rendu dans sa RunLoop, et qu'aucune classe UI n'est thread-safe de toute façon.
Et je ne peux que te conseiller les différentes sessions des CocoaHeads Rennes (disponibles en vidéo) où le sujet a été abordé.
La session de Thomas consistait en un tutoriel pour faire un jeu de zombies (zombies animés et qui marchent d'un bout à l'autre de l'écran et qu'il faut shooter avec des cranberries elles aussi animées...), jeu codé pendant la session (~1h) pour nous montrer ainsi comment prendre SpriteKit en main et quelles sont ses possibilités.
CocoaHeads Rennes #15 - Introduction à SpriteKit, Partie 1 (présentation théorique, ~20mn)
CocoaHeads Rennes #15 - Introduction à SpriteKit, Partie 2 (pratique et code, ~40mn)
CocoaHeads Rennes #17 - SpriteKit : Retour d'Expérience
Super merci beaucoup ! J'ai bien compris mon erreur avec les NSTimers, je vais recommencer avec Sprite Kit, ça m'entrainera pour plus tard si j'en aurai besoin (merci pour les formations !)!
Et pas de multithreading pour tout ce qui est relatif à l'UI, je note merci !
Dernière question puis je m'y mets : comment puis-je afficher une image sur la vue courante depuis une fonction d'une classe ?
Par exemple dans ma classe personnage, je ne peux pas par exemple mettre : [self.view addSubview:...]. Jusque maintenant, je mettais cette ligne de code dans ma classe correspondant à mon ViewController, mais je ne sais pas comment, uniquement en initialisant un objet d'une classe Personne, afficher une image sur le viewController ?
Merci encore à vous!
Convertir les modèles en Vues est le rôle du View Controller. C'est lui qui va créer, par exemple, les UIImageView qui correspondent à la Personne.
Ton cas est assez simple parce que la liste des Personnes n'a pas l'air de pouvoir changer: il lui suffit de savoir que le fichier a été chargé (le modèle est rempli), et créer une UIImageView pour chaque Personne, puis de l'ajouter à sa vue.
Merci pour ces liens, je vais regarder tout ça (hors sujet mais tellement content d'avoir ces ressources).
Je ne savais pas qu'il y avait une session cocoaHeads sur spriteKit et moi aussi ça m'intéresse. Merci pour les liens