CocoaPods: Différentes versions d'un même Pod

LarmeLarme Membre
mars 2016 modifié dans API UIKit #1

Mon problème actuel est celui montré ici.


 


Apparemment, cela est possible depuis 2014. En 2013, cela ne semblait pas être le cas.


 


Mon cas:


PersonalPrivatePod utilise AFNetworking (~> 2.0)

Current Project
 utilise AFNetworking (~> 1.3.4)


 


Donc, quand je fais un pod update, j'ai ceci:



[!] Unable to satisfy the following requirements:
- `AFNetworking (~> 1.3.4)` required by `Podfile`
- `AFNetworking (~> 2.0)` required by `PersonalPrivatePod (0.0.1)`

Cependant, je suis perdu sur le comment de la résolution :


- quelque chose à  mettre explicit dans mon PodFile de mon projet courant ?


- quelque chose à  spécifier dans le .podspec de PersonalPrivatePod ?


 


Ma version de CocoaPods1.0.0.beta.4


 


Une solution serait de tout passer à  AFNetworking 3, mais j'aimerais éviter (car cela nécessite de nombreux tests).


 


 


J'ai l'impression par contre, je vais être confronté au problème des différentes doubles names.


Réponses

  • AliGatorAliGator Membre, Modérateur
    Si ce sont les mêmes projets qui sont visés in-fine, ce n'est pas possible, car cela mènerai à  des Duplicate Symbols puisque tu link 2 versions de la même lib (ayant des symboles conflictuels) à  un même target final. Et ceci n'est pas lié à  CocoaPods à  proprement parler, c'est juste pas envisageable comme type de configuration projet

    Par exemple, même sans parler de CocoaPods, si tu as un projet ajoutais un framework AFNetworking-1.3.4.framework au target de ton application, et que ce target de ton application est aussi linké à  à  MonFramework.framework, qui lui dépend de AFNetworking-2.0.0... si tu essayes de linker tout ça, à  la fin tu auras des Duplicate Symbols et ne pourra pas compiler, c'est logique.
  • LarmeLarme Membre
    mars 2016 modifié #3

    C'est bien ce qu'il me semblait: Duplicate Symbols en vue.


    C'est juste le post sur le GitHub qui m'a mis le doute, car je n'ai pas compris grand chose de ce qu'il s'est dit là -bas.


  • AliGatorAliGator Membre, Modérateur
    Le post sur GitHub parle de quand un de tes targets nécessite AFNetworking ~>1.3 alors que l'autre nécessite ~>1.2

    Dans ce genre de cas, le solveur de dépendances de CocoaPods peut trouver une version qui convient à  tout le monde (la 1.3) car conformément au semantic versioning (semver.org) la 1.3.0 est logiquement rétro-compatible avec la 1.2.0 (tant que tu n'inclémentes pas le numéro de version major/breaking).

    Du coup dans ce cas là , CocoaPods ne va pas t'installer AFNetworking en version 1.2 et 1.3 (là  ça ferait effectivement des Duplicate Symbols) mais une seule version d'AFNetworking, la 1.3, qui se trouve être compatible avec tes deux targets, celui qui nécessite une version 1.3 ou supérieure, et celui qui nécessite une version 1.2 ou supérieur (1.3 pouvant donc correspondre dans ce cas).

    Par contre il n'aurait pas pu si un target nécessitait une version 1.x alors qu'un autre nécessite une version 2.x, car d'après le semantic versioning le changement de version majeure indique une incompatibilité d'API.

    C'est d'ailleurs pour cela qu'on utilise bien souvent l'opérateur "~>x.y" pour les numéros de version, le "~>" voulant dire (tu peux avoir une valeur supérieure pour le dernier digit de cette version, mais pas pour les autres digits (donc "~>1.2" signifie "toute version 1.x supérieure ou égale à  1.2 " mais donc pas 2.x ou supérieur).
    Comme ça en utilisant cette notation "~>.x.y" on dit à  CocoaPods "tu peux prendre une version mineure supérieure si besoin car d'après semver.org ça va rester retrocompatible, mais pas une version majeure différente car l'API risquerait de ne pas être compatible". Et c'est comme ça que si un target demande "~> 1.2" alors qu'un autre demande "~> 1.3" alors on pourra utiliser une version version unique pour combler les 2 dépendances du moment qu'elle est >= 1.3 mais <2.0
  • LarmeLarme Membre
    mars 2016 modifié #5

    Merci pour ces explications.


    Tu as mis en avant les petites subtilités qui font que malheureusement pour moi ce n'est pas possible, mais je comprends dorénavant pourquoi dans le cas cité cela fonctionne.


     


    Donc malheureusement, je suis sur des versions réellement différentes (1.x & 2.x) qui ont trop de changements pour co-exister sans avoir de duplicate symbols (double "import"), là  où de légères modifications (1.x & 1.z) ne devraient (en théorie, mais AFNetworking respecte cela) ne devraient apporter que de petites améliorations en faisant basant la plus récente version sur la plus ancienne (import unique de la version plus récente et les appels basés sur la version antérieure devraient fonctionner).


  • AliGatorAliGator Membre, Modérateur
    C'est tout à  fait ça !
  • FKDEVFKDEV Membre

    Tu peux faire ton propre repository où tu aurais la version de 1.3.14 AFNetworking dont les classes seraient renommées en AF1XNetworking.


    Après dans ton code, tu peux t'en tirer sans trop de modification en utilisant des #define :


     


    #define AFNetworking AF1XNetworking

     


    Pour des gros projets, comme AFNetwoking, il pourrait y avoir une convention qui consisterait à  mettre à  disposition les anciennes versions majeures avec de nouveaux noms sur cocoapods.


  • LarmeLarme Membre
    mars 2016 modifié #8


    Tu peux faire ton propre repository où tu aurais la version de 1.3.14 AFNetworking dont les classes seraient renommées en AF1XNetworking.


    Après dans ton code, tu peux t'en tirer sans trop de modification en utilisant des #define :



    #define AFNetworking AF1XNetworking

    Pour des gros projets, comme AFNetwoking, il pourrait y avoir une convention qui consisterait à  mettre à  disposition les anciennes versions majeures avec de nouveaux noms sur cocoapods.




     


    Finalement, j'ai upgradé le projet qui appelait la version 1.x en 2.x en créant un Wrapper qui permet de " gérer " les deux modes d'appels.


    Il hérite/appelle les bonnes classes en 2.x tout en gardant également la manière d'appeler en 1.x.


    Je suis encore en phase de tests/clean pour vérifier que tout marche correctement, mais cela semble fonctionner.


     


    ie:


    getPath:parameters:success:failure: appelle GET:parameters:success:failure: etc.


    Il y a quelques incohérences au niveau des retours (l'un est un void, l'autre est un AFHTTPRequestOperation) notamment, mais notre code n'en avait pas besoin auparavant, donc bon.


    Les blocks (success/failure) sont heureusement les mêmes. Je rajouterais sûrement prochainement un __deprecated_msg() afin d'avoir une certaine cohérence dans le code, mais ce n'est pas encore à  l'ordre du jour.


     


    Ce wrapper sera donc à  modifier si on veut passer à  la 3.x, même si cela demandera sûrement plus de travail (blocks différents, etc.)


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