Utiliser une même classe pour plusieurs target
Bonjour à tous,
Dans mon app iOS je dois aller chercher des données sur un serveur. Je fais donc appel à une classe que j'ai appelée "Network" qui est une sous classe de NSObject. Seulement j'aimerais porter mon app iOS sur watchOS et donc ne pas avoir à tout réécrire et surtout je vois un coté pratique : ne pas avoir à modifier la même chose à deux endroits différents. J'aimerais donc pouvoir utiliser cette classe sur iOS et watchOS.
Dans Target Membership, j'ai donc coché mon target iOS et mon extension watchOS. Mais le problème c'est que ma classe Network contient des frameworks non compatibles avec watchOS (AddressBook par exemple).
Comment pourrais-je régler ce problème ou à la limite m'organiser autrement pour ne pas avoir à tout réécrire deux fois la même chose à chaque modification de code ? Avez-vous une idée ?
Merci d'avance
Réponses
Il parait tout à fait illogique qu'une classe dédiée au réseau ait un lien avec un truc qui n'a rien à voir. C'est totalement en contradiction avec les principes "SOLID" : https://fr.wikipedia.org/wiki/SOLID_(informatique),et en particulier le "S" : Single Responsibility Principle.
La réponse à la question est donc : respecter au maximum ces principes, et, franchement, hormis pour la substitution de Liskov qui est un peu tricky à comprendre, ce n'est pas très compliqué...
Merci zoc pour ta réponse. A vrai dire je pensais me simplifier la tache. Mais inutile alors merci bien
La séparation des responsabilités est importante pour avoir un code propre et facile a maintenir.
Mais tu peux te retrouver avec du code que tu veux compiler ou pas selon l'os même en étant respecté bien le le principe de la responsabilité unique. Tu peux utiliser les conditions de compilation dans ce cas la
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithCAPIs.html#//apple_ref/doc/uid/TP40014216-CH8-XID_13
Tu peux utiliser des instructions du précompilateur pour supprimer de la compilation les parties qui utilisent le framework qui n'est pas disponible sur watchOS.
Oui y a pas de préprocesseur en Swift mais y a les "build configuration".
On peut faire un import conditionnellement par exemple :
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithCAPIs.html#//apple_ref/doc/uid/TP40014216-CH8-XID_21
Donc ce ne sont plus vraiment des "macros" qui sont remplacées par des valeurs, mais juste des flags Oui/Non.
Et il n'y a pas non plus de #define pour définir une valeur de preprocessor via le code : on ne peut tester que des valeurs un on a précédemment définies via le Build Setting idoine.
C'est ainsi qu'en Swift on peut tester "#if DEBUG" pour savoir si la Preprocessor Definition "DEBUG" a été définie ou pas, mais on ne peut pas tester "#if MODE > 1" ou utiliser "MODE" comme une constante dans le code : les Preprocessor Définitions ne peuvent s'utiliser que pour être testées via un "#if" et pas autrement.
En fait on peut dont dire que les Preprocessor Macros n'existent plus du tout en Swift (ces macros qui avaient une valeur, pouvaient être définies avec un #define et comparées à d'autres valeurs ou utilisées dans le code) et que le seul opérateur qui nous reste c'est "#if" qui peut tester des choses comme l'OS cible ou si un flag (comme DEBUG) a été défini dans les Build Settings ou pas.
Mais ça ne va pas beaucoup plus loin et c'est tant mieux car ça évite les trucs alambiqués à suivre, les problèmes de priorités d'opérateurs ou les galères de debugging
Zut alors, on ne pourra plus faire de concours sur le code le plus compact et le plus illisible possible ! Apple, les geeks ne te disent pas merci ..
La question est de savoir si le champ de possibilités réduit de Swift sera suffisant dans la pratique. Seul le temps nous le dira.
Bonjour à tous et pardon pour le temps de réponse un peu long.
J'ai donc décidé finalement d'utiliser une classe différente pour chacun de mes target. J'ai commencé à mettre des tests un peu partout au début, puis je me suis vite rendu compte que la lecture du code devenait plus archaà¯que qu'autre chose. Je suis donc passé à une classe par target. La gestion du projet sera peut-être un peu plus longue, mais beaucoup plus agréable.
Merci pour vos réponses et je m'excuse à nouveau pour le temps de réponse.
Je remonte un peu ce sujet, car c'est une problématique actuellement sur laquelle je planche un peu...
Mon problème est un peu différent :
- Multi-apps/Targets, qui ont une sorte de base commune, mais customisables.
En bref, un peu comme si vous aviez Candy Crush, un autre jeu de King qui y ressemble (j'crois qu'ils en ont un avec des légumes), etc. Des déclinaisons en fonction des clients à partir de notre coe“ur de métier si on peut dire... J'espère pour eux qu'ils ont même gestion des mécanismes qui détecte les alignements de 3 bonbons ou plus.
- Potentiellement multi-plateformes (orienté Apple): Mac OS X, tvOS, iOS, WatchOS.
Alors, j'ai l'impression que c'est un peu plus vaste/complexe que le sujet initial de Benjo, mais cela pourrait peut-être servir de base pour mes autres projets à venir qui le seront moins. En bref, si j'applique cette méthode à un truc complexe, si ce n'est pas trop lourd, je pourrais peut-être l'appliquer à d'autres projets un peu plus simples (moins de targets, etc.)
Je suis en train donc d'y réfléchir, et voici quelques idées/pistes que j'aimerais vous soumettre :
- Créer des classes mères, pas vraiment totalement abstraites non plus, mais qui permettrait d'homogénéiser le tout, et qu'on pourrait dériver en fonction de nos besoins. C'est notamment là -dedans, qu'on pourrait avoir ces fameux if iOS, if Mac OSX, et donc potentiellement y cacher une partie des "trucs chiants" qui rendent un peu plus illisible le code.
- Mettre ces "classes mères" dans des petits repo privés et utiliser CocoaPods pour ces derniers.
- M'inspirer de MagicalRecord et de sa manière de virer les "MR_" devant les noms de méthodes. Je ne sais absolument pas ce que cela va donner, si c'est réalisable ou non, contraignant ou non, mais c'est une idée que j'aimais: avoir des InitialClients_nomDeMethod.
J'avoue que c'est actuellement plus de la m*st*r*b*t**n intellectuelle qu'autre chose, mais ça devient mon p'tit casse-tête personnel actuel. J'aimerais commencer à réellement coder quelques apps à mon compte, et autant prendre les devants en fonction de mes petites idées...
@Larme si tu fais du Swift oublie les classes abstraites, mères,.... pense plutôt aux protocols et a leurs extensions pour ton architecture.
Non, j'aime les crochets !
Tu peux, quand même, utiliser les protocols avec les crochets. Et penses-tu de créer un/des framework(s)
Les crochets, pas les fouets !
Bah... si ça peut faire passer la mode des design patterns...
Bah... mais oui