42 votes

Quelle compilation conditionnelle utiliser pour basculer entre le code spécifique Mac et iPhone?

Je suis en train de travailler sur un projet qui comprend une application Mac et une application iPad qui partager du code. Comment puis-je utiliser le conditionnel compiler les commutateurs à exclure Mac-code spécifique à partir de l'iPhone de projet et vice-versa? J'ai remarqué qu' TARGET_OS_IPHONE et TARGET_OS_MAC sont à la fois 1, et donc ils sont tous les deux toujours vrai. Est-il un autre interrupteur que je peux utiliser seulement renverra true lors de la compilation pour une cible spécifique?

Pour la plupart, j'ai reçu les fichiers de coopérer en déplaçant #include <UIKit/UIKit.h> et #include <Cocoa/Cocoa.h> dans le précompiler les en-têtes pour les deux projets. Je suis le partage de modèles et certaines utilitaire de code qui récupère des données à partir de flux RSS et Evernote.

En particulier, l' [NSData dataWithContentsOfURL:options:error:] fonction prend une autre constante pour le paramètre options iOS 3.2 et les versions antérieures de Mac OS 10.5 et plus tôt qu'elle ne l'est pour iOS 4 et Mac OS 10.6. Le conditionnel que j'utilise est:

#if (TARGET_OS_IPHONE && (__IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_3_2)) || (TARGET_OS_MAC && (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5))

Cela semble fonctionner, mais je veux m'assurer que c'est l'épreuve des balles. Ma compréhension est que si la version Mac est mis à 10.6, mais la version iOS est fixé à 3,2, il continuera d'utiliser les nouvelles constantes, même si c'est de la compilation pour iOS 3.2, qui semble incorrecte.

Merci d'avance pour toute aide!

69voto

Steven Fisher Points 22249

Vous avez fait une erreur dans vos observations. :)

TARGET_OS_MAC 1 lors de la construction d'un Mac ou d'une application iPhone. Vous avez raison, il est tout à fait inutile pour ce genre de chose.

Toutefois, TARGET_OS_IPHONE 0 lors de la construction d'une application Mac. J'utilise TARGET_OS_IPHONE dans mes en-têtes de tous les temps à cet effet.

Comme ceci:

#if TARGET_OS_IPHONE
// iOS code
#else
// OSX code
#endif

Voici un grand tableau sur ceci: http://sealiesoftware.com/blog/archive/2010/8/16/TargetConditionalsh.html

8voto

Louis Gerbarg Points 33025

"La bonne chose à faire est d'utiliser la plus récente des constantes, parce que si vous regardez l'en-tête, vous verrez qu'elles sont déclarées équivalentes aux anciens de l'enum, ce qui signifie que les nouvelles constantes, même sur les anciennes versions (deux constantes de compilation à la même chose, et depuis les énumérations sont compilés dans l'application, ils ne peuvent pas changer sans casser la compatibilité binaire). La seule raison de ne pas le faire est si vous avez besoin de continuer à construire contre les anciens Kits de développement logiciel (qui est autre chose que de soutenir les anciennes versions, ce que vous pouvez faire lors de la compilation contre les nouveaux Kits de développement logiciel).

Si vous avez réellement voulu utiliser différents indicateurs basés sur la version de l'OS (parce que la nouvelle version a ajouté des nouvelles fonctionnalités, plutôt que de simplement renommer une constante), alors il y a deux choses sensibles que vous pouvez faire, ni de qui votre macro ci-dessus accomplit:

  1. À utiliser toujours le vieux drapeaux, à moins que le min de la version autorisée est supérieure à la version qu'ils ont été introduits dans (quelque chose comme ça):

    #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060)
      NSDataReadingOptions  options = NSDataReadingMapped;
    #else
      NSDataReadingOptions  options = NSMappedRead;
    #end
    
  2. Conditionnellement utiliser seul les nouvelles valeurs dans les compositions qui peut uniquement sur les nouvelles versions, et de les compiler en code pour déterminer les drapeaux au moment de l'exécution pour les versions qui prennent en charge les deux versions:

    #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060)
      NSDataReadingOptions  options = NSDataReadingMapped;
    #else
      NSDataReadingOptions  options;
      if ([[UIDevice currentDevice] systemVersion] compare:@"4.0"] != NSOrderedAscending) {
         options = NSDataReadingMapped;
      } else {
        options = NSMappedRead;
      }
    #end
    

Notez que si vous faisiez cette comparaison est un lot que vous souhaitez ranger le résultat de l' [[UIDevice currentDevice] systemVersion] compare:@"4.0"] quelque part. Vous aussi veulent généralement explicitement test pour les fonctionnalités en utilisant des choses comme la faiblesse de la liaison au lieu de faire la version compare, mais ce n'est pas une option pour les énumérations.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X