2012-06-15 8 views
8

que he visto en algunos proyectos algo como:¿Cómo saber en qué Mac OS se está ejecutando la aplicación?

#if ..... 
    code... 
#endif 

, pero no puedo encontrar ahora ...
Digamos, por ejemplo, si la aplicación se está ejecutando en el 10,8 aplicación hace 1 cosa , si no la aplicación hace otra cosa. ¿Cuál es el código para verificar si se está ejecutando en 10.8?
Gracias.

+0

Hice una comprobación rápida, y esta respuesta podría ayudarlo: http://stackoverflow.com/questions/157759/how-can-i-determine-the-running-mac-os-x-version-programmatically – CBredlow

+5

Un CPP # define/# si * * no * es tu amigo aquí. Es un conmutador de * compilación * (por ejemplo, qué plataforma/función está siendo * dirigida *). –

+0

#if .... #endif es un preprocesador que se ejecuta en tiempo de compilación, lo utilizo para determinar entre dev, qa (prueba) y versión. – Popeye

Respuesta

23

Probablemente esté haciendo la pregunta incorrecta. Excepto en casos muy raros, no debería importar qué versión del sistema está ejecutando el usuario. En su lugar, debe verificar si está disponible lo específico que le interesa.

Por ejemplo, si Apple introduce una clase MagicHologram en Mac OS X 10.9 que desea utilizar, no verifica si el usuario ejecuta Mac OS X 10.9. En cambio, verifica si la clase MagicHologram está disponible. Si es así, puedes usarlo. Si no, no está disponible. Ni siquiera importa por qué. Tal vez están ejecutando 10.8. Pero tal vez es cinco años después, y Apple decidió abandonar la clase MagicHologram por completo.

(Además, tenga en cuenta que lo que se necesita a débil enlace a HologramKit, la biblioteca que proporciona la clase MagicHologram.)

Del mismo modo, si introducen un nuevo método para NSString, en lugar de revisar el sistema operativo versión que verificaría si NSString conoce el nuevo método.

Dicho esto, NSApplication.h incluye una constante externa llamada NSAppKitVersionNumber. Puede comparar esto con constantes como NSAppKitVersionNumber10_7 que (debe tenerse en cuenta) son números como 1138, no 10.7.Solo hay unos pocos lugares adecuados, principalmente donde las clases eran privadas e indocumentadas, pero obtuvieron cambios importantes antes de documentarse y convertirse en parte de las partes públicas del SDK. Además, podría ser útil si quieres evitar un error específico que se ha solucionado desde entonces.

Para recapitular:

  1. Detectar las clases y los métodos individuales, que deben cubrir el 99,44% de los casos.
  2. Use NSAppKitVersionNumber y NSAppKitVersionNumber10_7 para cubrir aquellos casos en los que la detección de clase o método le correspondería.
  3. Esos dos primeros puntos cubren todos casos normales. No deberías ir más allá. Pero si debe tener un comportamiento basado en la versión humana, mire la respuesta de abarnert a continuación. Es la mejor manera de obtenerlos.
  4. No utilice operatingSystemVersionString, que se menciona específicamente como no seguro para el análisis.

Referencias/más información:

  • SDK Compatibility Guide "Lea este documento si desea que la aplicación para apuntar a una versión específica o varias versiones de iOS o Mac OS X."
    • Using SDK-Based Development Describe cómo utilizar clases, métodos y funciones débilmente vinculados para admitir la ejecución en múltiples versiones de un sistema operativo.
-4

Puede obtener la versión del sistema operativo de esta manera:

NSString *version = [[NSProcessInfo processInfo] operatingSystemVersionString]; 

NSLog(version); 

Salida:

screenshot


Y veo Quiere recibir sólo la versión. Se puede hacer de la siguiente manera:

NSString *version = [[NSProcessInfo processInfo] operatingSystemVersionString]; 

NSRange range = NSMakeRange(8, 4); 
NSString *justVersion = [version substringWithRange: range]; 

NSLog(@"%@", justVersion); 

Resultado:

screenshot

Y para la comprobación:

if ([justVersion isEqualToString:@"10.7"]) { 
    code... 
} 
else { 
    ... 
} 
+8

En la documentación: "esta cadena no es apropiada para el análisis". –

+1

Esto está muy muy mal. –

+0

También tenga en cuenta que el formato de esa cadena varía según la configuración regional del usuario. –

2

Puede obtener la versión actual del comando uname -r (que es en realidad el lanzamiento del núcleo, aunque es fácil mapear en las versiones de Mac OS X), desde el comando sw_vers que le da el nombre de la versión, versión y identificador de compilación, o de la función Gestalt() (en las versiones actuales de Mac OS X, de todos modos). La forma más segura es probablemente leer el resultado de sw_vers que se encuentra en un formato estable que es fácil de analizar.

Sin embargo, tenga en cuenta que probablemente no desee saber en qué versión del sistema operativo se encuentra. Lo que probablemente quiera hacer es probar si una característica en particular está disponible. Puede hacerlo mediante marcos de enlaces débiles, mediante referencias débiles de clase, o inspeccionando si una clase responde a los selectores apropiados para la característica que le interesa.

11

Una forma rápida de hacerlo es:

if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_7) { 

    // Do stuff for Lion or later 
} 

Más here.

Puede ver todas las constantes disponibles en NSApplication.h, a las que puede acceder utilizando Open Quickly ... (Cmd-Shift O) en Xcode.

Los archivos de encabezado proporcionan material de lectura sorprendentemente interesante, si así lo desea.

+0

Creo que el acceso directo es Cmd-Shift-D de forma predeterminada – cdelacroix

+2

El problema es que no cubre todas las revisiones de Mac OS X, y no hay manera de hacerlo a prueba si (por ejemplo, si está intentando informe la versión del sistema operativo para fines de diagnóstico.) –

4

Como han dicho otros (y elegiría la respuesta de Steven Fisher), generalmente no desea obtener el número de versión.

Y si solo tiene que hacer comparaciones con una versión principal de OS X hasta la versión del SDK actual que está utilizando, NSAppKitVersionNumber (como en la respuesta de Monolo) es la forma correcta de hacerlo.

Si realmente necesita obtener el número de versión por alguna razón (por ejemplo, para registrar el análisis de sus usuarios, para que pueda decidir cuándo dejar de admitir 10.6.0-10.6.5), aquí le mostramos cómo hacerlo:

#import <CoreServices/CoreServices.h> 
SInt32 majorVersion, minorVersion, bugFixVersion; 
Gestalt(gestaltSystemVersionMajor, &majorVersion); 
Gestalt(gestaltSystemVersionMinor, &minorVersion); 
Gestalt(gestaltSystemVersionBugFix, &bugFixVersion); 

para 10.7.3, esto da MajorVersion = 10, minorVersion = 7, bugFixVersion = 3.

la documentación 10.7 elimina el párrafo que sugiere directamente Gestalt como la manera de obtener la versión del sistema operativo, pero es todavía no está en desuso o heredado, y no hay otras sugerencias. De hecho, cualquier otra forma de obtener esta información (análisis - [NSProcessInfo operatingSystemVersionString], llamando a sysctlbyname en "kern.osrelease" y convirtiendo la versión del kernel de Darwin a la versión de OS X, etc.) está explícitamente contraindicada en alguna parte.Entonces, esta es la manera de hacerlo, si realmente quieres.

Solo tenga en cuenta que, como las notas de la versión para el Sistema 6.0.4 lo dijeron en 1989, esta nueva API puede no ser permanente y podría eliminarse en una versión futura del sistema operativo.

+0

Asegúrese de hacer las comparaciones correctamente si está haciendo esto. Alguien en mi empresa (no yo (guiño)) escribió una vez una rutina que detectó 10.4.0 como anterior a 10.3.1, porque 0 era menor que 1. :) –

+0

@StevenFisher: Nunca he hecho eso; Acabo de hacer un mayor igual cuando quise decir más grande. :) Pero el problema más común es convertir todo en una cadena y luego comparar cadenas, que funciona perfectamente hasta que sale 10.4.10 (porque "10.4.10" es menor que "10.4.9"). Puede usar NSNumericSearch/kCFCompareNumerically para evitar esto, pero aún más fácil, simplemente compare los números antes de stringifying. – abarnert

0

Aquí está el código de cómo lo hago. Me encanta de esta manera, principalmente porque no tengo que A) Confiar en un NSTask o B) Confiar en cualquier E/S de archivo a la que muchos procesos tienen acceso.

static NSString* const kVarSysInfoVersionFormat = @"%@.%@.%@ (%@)"; 
static NSString* const kVarSysInfoKeyOSVersion = @"kern.osrelease"; 
static NSString* const kVarSysInfoKeyOSBuild = @"kern.osversion"; 

- (NSString *) _strControlEntry:(NSString *)ctlKey { 

    size_t size = 0; 
    if (sysctlbyname([ctlKey UTF8String], NULL, &size, NULL, 0) == -1) return nil; 

    char *machine = calloc(1, size); 

    sysctlbyname([ctlKey UTF8String], machine, &size, NULL, 0); 
    NSString *ctlValue = [NSString stringWithCString:machine encoding:[NSString defaultCStringEncoding]]; 

    free(machine); return ctlValue; 
} 

- (NSString *) getOSVersionInfo { 

    NSString *darwinVer = [self _strControlEntry:kVarSysInfoKeyOSVersion]; 
    NSString *buildNo = [self _strControlEntry:kVarSysInfoKeyOSBuild]; 
    if (!darwinVer || !buildNo) return nil; 

    NSString *majorVer = @"10", *minorVer = @"x", *bugFix = @"x"; 
    NSArray *darwinChunks = [darwinVer componentsSeparatedByCharactersInSet:[NSCharacterSet punctuationCharacterSet]]; 

    if ([darwinChunks count] > 0) { 

     NSInteger firstChunk = [(NSString *)[darwinChunks objectAtIndex:0] integerValue]; 
     minorVer = [NSString stringWithFormat:@"%ld", (firstChunk - 4)]; 
     bugFix = [darwinChunks objectAtIndex:1]; 

    } return [NSString stringWithFormat:kVarSysInfoVersionFormat, majorVer, minorVer, bugFix, buildNo]; 
} 

disfrutar!

2

Como dijo Steven Fisher, no debería verificar la versión del sistema sino la disponibilidad de la clase o método que desea utilizar.

La comprobación de si una clase específica es el uso disponibles

if ([NSHologram class]) { 
    // Create an instance of the class and use it. 
} else { 
    // The Hologram class is not available. 
} 

Para comprobar si un método específico es el uso disponibles

NSString* hologramText = @"Hologram"; 
if ([hologramText respondsToSelector:@selector(convertHologram)]) { 
    [hologramText convertHologram]; 
} 

Sin embargo, para la comprobación método, el método debe estar disponible en el sistema donde construyes tu aplicación, o de lo contrario obtendrás un error de compilación.

Cuestiones relacionadas