Estoy trabajando en un proyecto que incluye una aplicación para Mac y una aplicación para iPad que compartir el código. ¿Cómo puedo utilizar modificadores de compilación condicional para excluir Mac para el código específicas del iPhone proyecto y vice-versa? Me he dado cuenta de que TARGET_OS_IPHONE y TARGET_OS_MAC ambos a 1, y por lo tanto son siempre verdaderas. Hay otro interruptor puedo usar que sólo devolverá true cuando la compilación para un objetivo específico?

Para la mayor parte, me he metido los archivos a cooperar moviendo #include <UIKit/UIKit.h> y #include <Cocoa/Cocoa.h> en el precompilar las cabeceras de los dos proyectos. Voy a compartir modelos y algunos utilidad de código que obtiene los datos a partir de fuentes RSS y Evernote.

En particular, la [NSData dataWithContentsOfURL:options:error:] función toma una constante diferente para el parámetro de opciones de iOS 3.2 y versiones anteriores, y Mac OS 10.5 y versiones anteriores de lo que se hace para iOS 4 y Mac OS 10.6. El condicional yo estoy usando es:

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

Esto parece funcionar, pero quiero asegurarme de que esto es a prueba de balas. Mi entendimiento es que si la versión de Mac está ajustado a 10.6, pero la versión de iOS se establece en 3.2, se usará el nuevo constantes incluso si es compilar para iOS 3.2, que parece incorrecta.

Gracias de antemano por cualquier ayuda!

InformationsquelleAutor Jose Ibanez | 2010-07-05

4 Comentarios

  1. 65

    Que has cometido un error en sus observaciones. 🙂

    TARGET_OS_MAC será 1 cuando la construcción de una Mac o una aplicación para iPhone. Tienes razón, es bastante inútil para este tipo de cosas.

    Sin embargo, TARGET_OS_IPHONE es 0 cuando la construcción de una aplicación de Mac. Yo uso TARGET_OS_IPHONE en mi encabezados todo el tiempo para este propósito.

    Como este:

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

    Aquí es un gran gráfico en esta:
    http://sealiesoftware.com/blog/archive/2010/8/16/TargetConditionalsh.html

    • Por desgracia, TARGET_OS_IPHONE parece ser definido en cualquier caso, si usted tiene un proyecto para iOS y OSX.
    • Sí. Se define como 0 para OSX, 1 para iOS. Usted necesidad de utilizar #if TARGET_OS_IPHONE, no #ifdef TARGET_OS_IPHONE. Se añadió un ejemplo.
    • Por cierto, la tabla es de Apple «en tiempo de ejecución wrangler». Si la realidad parece estar en desacuerdo con él, la pregunta de la realidad. 🙂
  2. 8

    «La cosa correcta a hacer, es simplemente el uso de las nuevas constantes, porque si nos fijamos en el encabezado verás que son declarados equivalentes a los viejos en el enum, lo que significa que el nuevo constantes funcionará incluso en las versiones antiguas (dos constantes de compilación para la misma cosa, y desde las enumeraciones se compilan en la aplicación que no se puede cambiar sin romper la compatibilidad binaria). La única razón para no hacerlo es que si usted necesita para continuar la construcción contra la mayor Sdk (que es una cosa diferente de apoyar a las versiones anteriores, que se puede hacer mientras se compila contra los nuevos SDKs).

    Si en realidad quería utilizar diferentes indicadores basados en la versión del sistema operativo (porque la nueva versión añadido una nueva funcionalidad, frente a sólo el cambio de nombre de una constante), entonces hay dos cosas sensibles que usted puede hacer, ni de que su macro anterior lleva a cabo:

    1. Utilizar siempre las viejas banderas, a menos que el min versión permitido es mayor que la versión que se introdujeron en (algo así):

      #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060)
        NSDataReadingOptions  options = NSDataReadingMapped;
      #else
        NSDataReadingOptions  options = NSMappedRead;
      #end
    2. Condicionalmente utilizar sólo los nuevos valores en las generaciones que puede en las nuevas versiones, y la compilación en código para determinar las banderas en tiempo de ejecución para las generaciones que soporte ambas versiones:

      #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

    Tenga en cuenta que si en realidad estaban haciendo esta comparación, una gran cantidad que usted quiere guardar el resultado de la [[UIDevice currentDevice] systemVersion] compare:@"4.0"] en algún lugar. Usted también quiere explícitamente de prueba para las características de uso de las cosas como la débil vinculación en lugar de hacer la versión compara, pero que no es una opción para las enumeraciones.

    • Gracias! Esto es lo bueno, pero creo que aún puede haber algunos problemas aquí. En las Opciones de Compilación para el Objetivo, hay dos configuraciones distintas en virtud de la Implementación, Mac OS X Destino de la Implementación y el iPhone OS Implementación de Destino. En estos dos ejemplos, si el Mac OS X Implementación de Destino se establece en Mac OS X 10.6, se hará uso de la nueva enumeración, incluso si usted está construyendo para el iPhone OS 3.2. Hay una manera, en tiempo de ejecución o de otra manera, para determinar qué sistema operativo es el objetivo?
    • Estás confundiendo la configuración en el Xcode inspector con lo que en realidad es enviado para el compilador. Ambos campos están disponibles debido a que algunos tipos de objetivos (como las bibliotecas estáticas) puede ser construido para ambas plataformas, pero sólo el campo correspondiente a la plataforma integrada se utiliza. Usted nunca tendrá que determinar en tiempo de ejecución que OS está siendo atacado, usted sabe que el sistema operativo en tiempo de compilación (que no son compatible con el binario, y el uso de los distintos procesadores). Sólo se necesita determinar en tiempo de ejecución entre las versiones del mismo sistema operativo, como único binario podría ser ejecutado en contra de las diferentes versiones.
  3. 7

    Las macros se definen en el SDK de archivo de encabezado TargetConditionals.h. Tomado de la 10.11 SDK:

    TARGET_OS_WIN32           - Generated code will run under 32-bit Windows
    TARGET_OS_UNIX            - Generated code will run under some Unix (not OSX) 
    TARGET_OS_MAC             - Generated code will run under Mac OS X variant
       TARGET_OS_IPHONE          - Generated code for firmware, devices, or simulator 
          TARGET_OS_IOS             - Generated code will run under iOS 
          TARGET_OS_TV              - Generated code will run under Apple TV OS
          TARGET_OS_WATCH           - Generated code will run under Apple Watch OS
       TARGET_OS_SIMULATOR      - Generated code will run under a simulator
       TARGET_OS_EMBEDDED       - Generated code for firmware

    Ya que todo es un «Mac OS X variante» aquí, TARGET_OS_MAC no es útil en este caso. Para compilar específicamente para macOS, por ejemplo:

    #if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR && !TARGET_OS_EMBEDDED
        //macOS-only code
    #endif

    Actualización: Nuevas cabeceras (Xcode 8+?) ahora han TARGET_OS_OSX definido específicamente para macOS. (h/t @OldHorse), así que esto debería funcionar:

    #if TARGET_OS_OSX
     //macOS-only code
    #endif
  4. 2

    El conjunto de macros para usar, incluye ahora TARGET_OS_OSX:

        TARGET_OS_WIN32           - Generated code will run under 32-bit Windows
        TARGET_OS_UNIX            - Generated code will run under some Unix (not OSX) 
        TARGET_OS_MAC             - Generated code will run under Mac OS X variant
           TARGET_OS_OSX          - Generated code will run under OS X devices
           TARGET_OS_IPHONE          - Generated code for firmware, devices, or simulator
              TARGET_OS_IOS             - Generated code will run under iOS 
              TARGET_OS_TV              - Generated code will run under Apple TV OS
              TARGET_OS_WATCH           - Generated code will run under Apple Watch OS
                 TARGET_OS_BRIDGE          - Generated code will run under Bridge devices
           TARGET_OS_SIMULATOR      - Generated code will run under a simulator
           TARGET_OS_EMBEDDED       - Generated code for firmware

    Parece funcionar ok para la compilación condicional de macOS código.

Dejar respuesta

Please enter your comment!
Please enter your name here