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

  • zoczoc Membre
    décembre 2015 modifié #2

    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 :)


  • samirsamir Membre
    décembre 2015 modifié #4

    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



    #if os(iOS)
    // Code pour iOS
    #elseif os(watchOS)
    // Code
    #endif

    https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithCAPIs.html#//apple_ref/doc/uid/TP40014216-CH8-XID_13


  • FKDEVFKDEV Membre
    décembre 2015 modifié #5

    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.



    //compile sous watchOS

    #if !TARGET_OS_WATCH
    //non disponible sur watchOS

    #endif

  • CéroceCéroce Membre, Modérateur
    En espérant que la classe n'est pas écrite en Swift, puisqu'il n'y a pas de préprocesseur dans ce langage.


  • En espérant que la classe n'est pas écrite en Swift, puisqu'il n'y a pas de préprocesseur dans ce langage.




     


    Oui y a pas de préprocesseur en Swift mais y a les "build configuration".


     


    On peut faire un import conditionnellement par exemple :



    #if os(iOS)
        import Foundation
        import UIKit
    #else
    ....
    #endif

    https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithCAPIs.html#//apple_ref/doc/uid/TP40014216-CH8-XID_21

  • CéroceCéroce Membre, Modérateur
    décembre 2015 modifié #8
    @samir: intéressant, je ne connaissais pas. Effectivement, ça règle une partie des besoins d'un précompilateur. ça a été introduit dans Swift 2 ?
  • AliGatorAliGator Membre, Modérateur
    décembre 2015 modifié #9
    Il y a un pré processeur en Swift mais il est très simplifié. Ce qu'on pouvait faire avant avec les #if et #ifdef maintenant on ne peut faire que l'équivalent du #ifdef à  savoir tester si une "Preprocessor Definition" a été définie ou pas mais pas tester sa valeur.

    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 ..

  • CéroceCéroce Membre, Modérateur
    @Draken: on peut écrire de la merde dans tous les langages. Le préprocesseur du langage C n'est pas vraiment en cause, il a permis des choses impossibles à  écrire autrement. Maintenant, il est vrai que j'ai vu des abominations permises par ce préprocesseur, notamment sur les définitions de types.

    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. 




  • @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 ! :p

  • Joanna CarterJoanna Carter Membre, Modérateur

    Non, j'aime les crochets ! :p



    Tu peux, quand même, utiliser les protocols avec les crochets. Et penses-tu de créer un/des framework(s)


  • Non, j'aime les crochets ! :P




    >:)



  • >:)




    Les crochets, pas les fouets !

  • AliGatorAliGator Membre, Modérateur
    Et moi j'ai une dent contre les Capitaines Crochets :D
  • tic tac, tic tac
  • @Larme si tu fais du Swift oublie les classes abstraites, mères,.... pense plutôt aux protocols et a leurs extensions pour ton architecture.


    Bah... si ça peut faire passer la mode des design patterns...
  • Joanna CarterJoanna Carter Membre, Modérateur

    Bah... mais oui 


Connectez-vous ou Inscrivez-vous pour répondre.