How to Determine the Os Version At Runtime in Os X or iOS (Without Using Gestalt)

How do I determine the OS version at runtime in OS X or iOS (without using Gestalt)?

On OS X 10.10 (and iOS 8.0), you can use [[NSProcessInfo processInfo] operatingSystemVersion] which returns a NSOperatingSystemVersion struct, defined as

typedef struct {
NSInteger majorVersion;
NSInteger minorVersion;
NSInteger patchVersion;
} NSOperatingSystemVersion;

There is also a method in NSProcessInfo that will do the comparison for you:

- (BOOL)isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion)version

Beware, although documented to be available in OS X 10.10 and later, both operatingSystemVersion and isOperatingSystemAtLeastVersion: exist on OS X 10.9 (probably 10.9.2) and work as expected. It means that you must not test if NSProcessInfo responds to these selectors to check if you are running on OS X 10.9 or 10.10.

On iOS, these methods are effectively only available since iOS 8.0.

How to get the OS Version String in MAC 10.10 without using gestalt

I'm guessing that you aren't building this with the 10.10 SDK, otherwise you could simply remove your call to objc_msgSend_stret and call operatingSystemVersion directly.

// Built with 10.10 SDK
if ([[NSProcessInfo processInfo] respondsToSelector:@selector(operatingSystemVersion)]) {
NSOperatingSystemVersion version = [[NSProcessInfo processInfo] operatingSystemVersion];
// do whatever you want with the version struct here
}
else {
UInt32 systemVersion = 0;
OSStatus err = Gestalt(gestaltSystemVersion, (SInt32 *) &systemVersion);
// do whatever you want with the systemVersion as before
}

If you're using an earlier SDK, then NSOperatingSystemVersion and -[NSProcessInfo operatingSystemVersion] are both undefined. Since you can't use -[NSProcessInfo operatingSystemVersion] without getting a compiler error, the safer way to call it and get the return value of a non-object type is with NSInvocation. This is still technically risky because you're assigning the return value to a different type of struct (MyOperatingSystemVersion vs. NSOperatingSystemVersion), but you have defined them both the same so it should be ok. I tested this with Xcode 5 / 10.9 SDK and it worked fine.

// Built with 10.9 or earlier SDKs
if ([[NSProcessInfo processInfo] respondsToSelector:@selector(operatingSystemVersion)]) {
MyOperatingSystemVersion version;
NSMethodSignature *methodSignature = [[NSProcessInfo processInfo] methodSignatureForSelector:@selector(operatingSystemVersion)];
NSInvocation *inv = [NSInvocation invocationWithMethodSignature:methodSignature];
inv.selector = @selector(operatingSystemVersion);
[inv invokeWithTarget:[NSProcessInfo processInfo]];
[inv getReturnValue:&version];
// do whatever you want with the version struct here
}
else {
UInt32 systemVersion = 0;
OSStatus err = Gestalt(gestaltSystemVersion, (SInt32 *) &systemVersion);
// do whatever you want with the systemVersion as before
}

That should take care of the problem, but the safest thing to do is build with the 10.10 SDK and use the first example.

How to check Mac OS X version at runtime

Update:

Use #define NSAppKitVersionNumber10_10_Max 1349

Old:

From 10.11 SDK

#define NSAppKitVersionNumber10_7_2 1138.23
#define NSAppKitVersionNumber10_7_3 1138.32
#define NSAppKitVersionNumber10_7_4 1138.47
#define NSAppKitVersionNumber10_8 1187
#define NSAppKitVersionNumber10_9 1265
#define NSAppKitVersionNumber10_10 1343
#define NSAppKitVersionNumber10_10_2 1344
#define NSAppKitVersionNumber10_10_3 1347

for 10.10.4 Its 1348.0(From NSLog output)

They increase decimal part for 10.10.x constant.

The workaround is to use CFBundleVersion value /System/Library/Frameworks/AppKit.framework/Resources/Info.plist on 10.11.

if (NSAppKitVersionNumber < 1391.12)
{
/* On a 10.10.x or earlier system */
}

NOTE: My OS X 10.11 build version is 15A244a. If someone have first build , Please update the value in if condition.

How can I determine the running Mac OS X version programmatically?

See this article here

But in short, if you're using carbon, use the Gestalt() call, and if you're using cocoa, there is a constant called NSAppKitVersionNumber which you can simply check against.

Edit: For Mac OSX 10.8 and above, don't use Gestalt() anymore. See this answer for more details: How do I determine the OS version at runtime in OS X or iOS (without using Gestalt)?

How to know what Mac OS the app is running on?

You're probably asking the wrong question. Except in very rare cases, you should not care what system version the user is running. Instead, you should be checking if the specific thing you're interested in is available.

For instance, if Apple introduces a MagicHologram class in Mac OS X 10.9 that you want to use, you don't check if the user is running Mac OS X 10.9. Instead, you check if the MagicHologram class is available. If it is, you can use it. If not, it's not available. It doesn't even matter why. Maybe they're running 10.8. But maybe it's five years later, and Apple's decided to drop the MagicHologram class entirely.

(Also, keep in mind that you'd need to weak link to HologramKit, the library that provides the MagicHologram class.)

Likewise, if they introduce a new method to NSString, instead of checking the OS version you'd check if NSString knows about the new method.

That said, NSApplication.h includes an external constant called NSAppKitVersionNumber. You can compare this to constants like NSAppKitVersionNumber10_7 which (it should be noted) are numbers like 1138, not 10.7. There's only a few places this is appropriate, mostly where classes were private and undocumented but got major changes before being documented and becoming a part of the public parts of the SDK. Also, it might be helpful if you want to avoid a specific bug that's been fixed since.

To recap:

  1. Detect individual classes and methods, which should cover 99.44% of your cases.
  2. Use NSAppKitVersionNumber and NSAppKitVersionNumber10_7 to cover those cases where class or method detection would lie to you.
  3. Those first two points cover all normal cases. You should go no further. But if you must have behaviour based on humane version, look at abarnert's answer below. It's the sanest way to get them.
  4. Don't use operatingSystemVersionString, which is specifically listed as not safe for parsing.

References/more information:

  • SDK Compatibility Guide "Read this document if you want your application to target a specific version or multiple versions of iOS or Mac OS X."

    • Using SDK-Based Development Describes how to use weakly linked classes, methods, and functions to support running on multiple versions of an operating system.

How to get actual name of Mac Operating System instead of version?

There is no API that I know of that would produce the product name of the current OS version. Even grepping for the product name in system locations yields surprisingly few results, and most of those in private frameworks. The only promising non-private match I found is in the Setup Assistant.app, and requires a horrible kludge to extract from a longer string:

NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/Setup Assistant.app/Contents/Resources/en.lproj/Localizable.strings"];
NSString *productName = [dict objectForKey:@"INSTALLATION_COMPLETE"];
if (productName) {
NSRange r = [productName rangeOfString:@" has been"];
if (r.location != NSNotFound) {
productName = [productName substringToIndex:r.location];
} else {
productName = nil;
}
}

This happens to work for Yosemite and El Capitan, and produces "OS X Yosemite" and "OS X El Capitan". But even with these two versions the kludgey nature reveals itself; the El Capitan string contains non-breakable spaces…

Apart from this (or a similar kludge using other files not meant to be used this way), one can of course obtain the numeric version and match it against a list of known product names, which would be my recommended solution, perhaps with the above kludge as a fallback.

Get OSX version with objective-c

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

Sorry for the formatting, I'm using my iPad to answer this.

Retrieving OS X version using Qt, c, c++

You could execute a command like sw_vers and read its output.

Example code, using QProcess:

osxversion.h

#ifndef OSXVERSION_H
#define OSXVERSION_H

#include

class OSXVersion : public QProcess
{
Q_OBJECT

int majr;
int minr;
int step;

OSXVersion();

public:

int majorOSRevision() const { return majr; }
int minorOSRevision() const { return minr; }
int stepOSRevision() const { return step; }

static OSXVersion * getVersion();

private slots:
void dataReady();
};

#endif // OSXVERSION_H

osxversion.cpp

#include "osxversion.h"

OSXVersion::OSXVersion() : QProcess(0)
{
majr = 0;
minr = 0;
step = 0;
connect(this, SIGNAL(readyRead()), this, SLOT(dataReady()));
}

OSXVersion * OSXVersion::getVersion()
{
OSXVersion * v = new OSXVersion();
v->start("sw_vers -productName");
v->waitForFinished();
return v;
}

void OSXVersion::dataReady()
{
int * v[3] = {&majr, &minr, &step};

QByteArray data = readAll();
QList tokens = data.split(':');
tokens = tokens[tokens.size() - 1].split('.');
for(int i=0; i {
*(v[i]) = QString(tokens[i]).toInt();
}
}

main.cpp

#include 
#include

#include "osxversion.h"

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

OSXVersion * version = OSXVersion::getVersion();

qDebug() << "OSX Version: "
<< version->majorOSRevision()
<< "."
<< version->minorOSRevision()
<< "."
<< version->stepOSRevision();

delete version;

return a.exec();
}


Related Topics



Leave a reply



Submit