Stratégie avec NSURLConnection
Flo
Membre
Bonjour à tous,
alors voilà , j'ai un model qui ressemble à ça A ->> B ->> C
où ->> représente une "relationship many to many"
Les B et les C on besoin d'être mis à jour via des données téléchargées d'internet, je vois deux stratégies :
1) A utilise une NSURLConnection pour télécharger toutes les données (des B et des C) et ensuite parse les données et mets à jour tout les B et les C.
2) Chaque B et chaque C possède une NSURLConnection, téléchargent leurs données chacun dans leur coin et se mette à jour tout seul.
Quelle stratégie serait la plus profitable selon vous ?
Je me pose également une autre question, dans une logique MVC, est-ce vraiment aux objets du model de faire ce genre de chose ?
Merci d'avance pour vos réponses
alors voilà , j'ai un model qui ressemble à ça A ->> B ->> C
où ->> représente une "relationship many to many"
Les B et les C on besoin d'être mis à jour via des données téléchargées d'internet, je vois deux stratégies :
1) A utilise une NSURLConnection pour télécharger toutes les données (des B et des C) et ensuite parse les données et mets à jour tout les B et les C.
2) Chaque B et chaque C possède une NSURLConnection, téléchargent leurs données chacun dans leur coin et se mette à jour tout seul.
Quelle stratégie serait la plus profitable selon vous ?
Je me pose également une autre question, dans une logique MVC, est-ce vraiment aux objets du model de faire ce genre de chose ?
Merci d'avance pour vos réponses
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
C'est difficile de répondre sans savoir ce que sont B et C.
Typiquement, si leurs instances sont très nombreuses, les NSURLConnection vont pomper beaucoup de ressources.
Si elles sont peu nombreuses, en programmation objet il est souvent plus facile et plus évolutif que chaque objet gère ses propres affaires, donc utilise sa propre NSURLConnection.
Oui, complètement.
En effet, les C peuvent être assez nombreux et ç'est vrai que je n'y avait pas pensé mais du coup ça fait un thread par objet...
Dommage parce que je trouvais également la stratégie 2 beaucoup plus "objet" et surtout beaucoup plus simple à réaliser
Donc t'aurais une pile (NSMutableArray?) d'objets indiquant {requête+demandeur}, et ton DownloadManager en dépile jusqu'à 5, et dès qu'il y a un download qui se finit il envoie l'élément téléchargé au demandeur associé, puis dépile la suivante.
Après si tu fais de ton DownloadManager un singleton (ou alors si tu le mets dans le AppDelegate par exemple enfin un truc comme ça) pour qu'il soit accessible par tous, bah c'est gagné :
1) Tu limites le nombre de NSURLConnections simultanées
2) Tu centralises tes downloads et ton module de récupération des données mises à jour
3) Tu restes objet tout de même.
YES ! ça dépote comme idée, j'aime bien !
J'y avais pas du tout pensé, merci !
Si ça t'intéresse je peux te filer la classe, c'est un singleton aussi.
Tu parles que ça m'intéresse ?
J'veux bien, merci c'est super sympa, histoire de récupérer quelques (bonnes) idées !
En gros le principe d'un singleton, si tu ne connais pas, c'est d'avoir une classe initialisée une seule fois dans ton programme, et utilisable par tout le monde. C'est un peu le principe de NSUserDefaults, t'as pas à faire de retain, release et tout le tralala, et toute tes classes partagent le meme NSUserDefaults.
De la même manière donc, tu appelles le singleton comme ceci (example pris à partir de mon code) :
comme si tu faisais
J'ai repris le principe de l'App Store pour charger les images, c'est à dire qu'à chaque décélération d'un scroll sur ma UITableView, je charge les URLs associés aux "visibleCells".
"picName", même si ça porte à confusion, est en fait l'URL de l'image sous forme NSString.
Après y'a deux autres méthodes qui retournent chacune un BOOL. Je pense qu'on aurait pu faire autremement mais bon, voici le fonctionnement :
Dans tout les cas, si l'un des deux retourne YES, mon controller ne rappelle pas le chargement des images pour les cells visibles. Il attend patiemment l'information du delegate :
Dès que mon controller est informé d'une "réussite", il appel immédiatement :
Toutes ces informations ((NSString*)picName, (BOOL)isLoading, (BOOL)isLoaded) sont stockées dans un NSDictionary par image.
Afin de vérifier facilement si une image est déjà en chargement ou déjà chargée, on stocke tous ces dictionnaires dans un "master dictionary" (j'aime bien ce terme ) qui aura comme clés les URLs (NSString) des images. Comme ça on peut simplement faire [picsList objectForKey:picName]!=nil par exemple pour vérifier l'existence de l'image demandée.
J'espère que ça t'aidera un peu quand même.. Bien que je suppose que ce n'est pas vraiment ce que tu veux, au moins tu peux voir comment est foutu un singleton, comment charger des images de façon "intelligentes" histoire de ne pas trop bousiller la mémoire de l'iPhone, etc...
Après, étant donné que les images sont appelées à n'être chargées que lorsque qu'un scroll a pris fin, il est évident qu'on se retrouve avec pas plus de .. boarf on va dire 5-6 images à charger d'un coup. ça rejoins un peu ce qu'expliquait Ali au niveau d'un download manager avec téléchargements simultanés limités.
Je t'ai fait un projet rapidos qui utilise ma classe "PicGetter" :
Bon ben oublie le projet d'exemple, mais le Singleton peut t'aider un brin.
(Faut vraiment que je m'habitue au fait que la section Mac soit passée à droite )
Côté singleton ça va je suis rodé, j'avais même essayé de faire un schéma d'héritage entre eux (sujet sur ce forum) mais bon c'était pas très concluant !
Merci pour ton exemple, je vois le principe du downloadManager !
Moi aussi je trouve ça super déroutant, j'ai déjà faillit poster dans la mauvaise section plusieurs fois !
Ha oui tiens ! Bonne idée aussi, je vais essayer de faire un mix de tout ça, ça m'a l'air d'être des stratégies plutôt propres et efficaces !
Merci à tous en tous cas
Oui en effet, je suis sur une appli "10.5 only"
Même schlum, grand adepte du multi threads, semble enfin admettre que c'est inutile !
http://forum.macbidouille.com/index.php?s=&showtopic=304559&view=findpost&p=3033706
On peut éventuellement envisager d'effectuer tous les chargements dans un thread séparé, histoire de soulager la run loop du main thread, sous réserves que ça soit vraiment nécessaire ...
Donc NSOperation et NSOperationQueue je suis aussi assez adepte quand le contexte s'y prête, mais là je suis pas sûr... Le seul but c'est d'éviter d'avoir 100 NSURLConnections tournant toutes en même temps, mais d'en limiter à par exemple 5 simultanées... Et là pas vraiment besoin de NSOperations, si ?
J'ai fait un test de ce genre, et les performances s'effondrent au delà de 50 threads (si je me souviens bien)
Je pense qu'il faut tenir compte du nombre de cores physiques/logiques
Et pour ce faire j'utilise cette méthode :
Toujours avec le schéma suivant A ->> B ->> C :
1. A fait remonter les données des B et des C pour construire l'URL pour tout le monde. (main thread)
2. A télécharge toutes les données d'un seul coup (une seule NSURLConnection en mode asynchrone ou A est le delegate)
3. A parse les données dans un thread concurrent pour construire un NSDictionary avec.
4. Les B et les C récupèrent chacun leur données respectives via le NSDictionary et se mettent à jour (dans le main thread).
Avantages :
- le parsing des données se fait en parallèle et la mise à jour finale des B et des C dans le main thread est beaucoup plus rapide.
Inconvénients:
- conso mémoire liée au NSDictionary intermédiaire ?
- est-ce que le boulot confié à A ne devrait du coup pas l'être plutôt à un controller ?
ça me semble pas mal comme ça aussi non ?
Moi, adepte du multi-thread ?
Au boulot, je suis sur un buffer manager qui fonctionne avec 9 threads et sans un seul mutex ;D
Une entrée, une sortie, une action d'entrée (décompression dans un format), une action de sortie (compression dans un autre format), un hash d'entrée, un hash de sortie, un hash intermédiaire, un thread de stats et un thread de smoothing