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

16

79

The Gestalt() function located in CarbonCore/OSUtils.h has been deprecated as of OS X 10.8 Mountain Lion.

I often use this function to test the version of the OS X operating system at runtime (see the toy example below).

What other API could be used to check the OS X operating system version at runtime in a Cocoa application?

int main() {
    SInt32 versMaj, versMin, versBugFix;
    Gestalt(gestaltSystemVersionMajor, &versMaj);
    Gestalt(gestaltSystemVersionMinor, &versMin);
    Gestalt(gestaltSystemVersionBugFix, &versBugFix);

    printf("OS X Version: %d.%d.%d\n", versMaj, versMin, versBugFix);
}
Antiscorbutic answered 17/6, 2012 at 16:9 Comment(2)
There is some discussion about the same thing in this question: #11055646Aegis
Gestalt APIs are VERY old (actually pre-carbon) and mostly deprecated. Although they're maintained still, and work, it is not a good idea to use them these days. Not even for runtime version...Cardoso
M
77

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.

Michalmichalak answered 2/6, 2014 at 23:8 Comment(9)
You may also using the following Objective-C category (BSD licensed) to use these new methods on older operating system versions: github.com/petroules/CocoaBackports/blob/master/CocoaBackports/… It should work back to OS X 10.5 and iOS 2.0 with MRC, ARC or GC and with older SDKs.Arrhythmia
Note that this will return the version of OS X if you run the app in the iOS Simulator.Closegrained
As of iOS 8 beta 4, the operatingSystemVersion method returns the correct version when running in the iOS simulator.Michalmichalak
doesn't work DP7. Don't have this selector (operatingSystemVersion)Clonus
isn't this just a tiny bit useless if it works on one minor version of each os only? maybe in the future this will be a valuable answer, but today it borders on useless...Olindaolinde
How to call [[NSProcessInfo processInfo] operatingSystemVersion] from C++ code?Puss
If I already know I'm on 10.10 I don't need to check! 😂 ------ On OS X 10.10Vetter
@Michalmichalak You wrote "you must not test" - could it be that you means "you need not test"? "must not" means "you should not do it", while you probably mean "you do not have to".Emaciated
What I wrote is correct. If you need to differentiate between macOS 10.9 and 10.10, do not use BOOL isYosemite = [NSProcessInfo.processInfo respondsToSelector:@selector(operatingSystemVersion)] since it would also return YES for macOS Mavericks (10.9) even though the selector is documented to be available since macOS Yosemite (10.10). By the way, are you still dealing macOS versions whose support ended more than 5 years ago?Michalmichalak
S
27

On the command line:

$ sysctl kern.osrelease
kern.osrelease: 12.0.0
$ sysctl kern.osversion
kern.osversion: 12A269

Programmatically:

#include <errno.h>
#include <sys/sysctl.h>

char str[256];
size_t size = sizeof(str);
int ret = sysctlbyname("kern.osrelease", str, &size, NULL, 0);

Darwin version to OS X release:

17.x.x. macOS 10.13.x High Sierra
16.x.x  macOS 10.12.x Sierra
15.x.x  OS X  10.11.x El Capitan
14.x.x  OS X  10.10.x Yosemite
13.x.x  OS X  10.9.x  Mavericks
12.x.x  OS X  10.8.x  Mountain Lion
11.x.x  OS X  10.7.x  Lion
10.x.x  OS X  10.6.x  Snow Leopard
 9.x.x  OS X  10.5.x  Leopard
 8.x.x  OS X  10.4.x  Tiger
 7.x.x  OS X  10.3.x  Panther
 6.x.x  OS X  10.2.x  Jaguar
 5.x    OS X  10.1.x  Puma

A Sample to get and test versions :

#include <string.h>
#include <stdio.h>
#include <sys/sysctl.h>

/* kernel version as major minor component*/
struct kern {
    short int version[3];
};

/* return the kernel version */
void GetKernelVersion(struct kern *k) {
   static short int version_[3] = {0};
   if (!version_[0]) {
      // just in case it fails someday
      version_[0] = version_[1] = version_[2] = -1;
      char str[256] = {0};
      size_t size = sizeof(str);
      int ret = sysctlbyname("kern.osrelease", str, &size, NULL, 0);
      if (ret == 0) sscanf(str, "%hd.%hd.%hd", &version_[0], &version_[1], &version_[2]);
    }
    memcpy(k->version, version_, sizeof(version_));
}

/* compare os version with a specific one
0 is equal
negative value if the installed version is less
positive value if the installed version is more
*/
int CompareKernelVersion(short int major, short int minor, short int component) {
    struct kern k;
    GetKernelVersion(&k);
    if ( k.version[0] !=  major) return major - k.version[0];
    if ( k.version[1] !=  minor) return minor - k.version[1];
    if ( k.version[2] !=  component) return component - k.version[2];
    return 0;
}

int main() {
   struct kern kern;
   GetKernelVersion(&kern);
   printf("%hd %hd %hd\n", kern.version[0], kern.version[1], kern.version[2]);

   printf("up: %d %d eq %d %d low %d %d\n",
        CompareKernelVersion(17, 0, 0), CompareKernelVersion(16, 3, 0),
        CompareKernelVersion(17, 3, 0), CompareKernelVersion(17,3,0),
        CompareKernelVersion(17,5,0), CompareKernelVersion(18,3,0));


}

Result on my machine macOs High Sierra 10.13.2

17 3 0
up: -3 -1 eq 0 0 low 2 1
Steno answered 28/7, 2012 at 1:2 Comment(2)
Note that these are the same results you get from uname (discussed in Carl Norum's answer). They're kernel version numbers, which map somewhat to OS releases, but not in an obvious way.Neuroglia
Never use this to determine the OS X or iOS version. While you might be able to arithmetically determine one version from another for OS X right now, such comparison is not guaranteed to work in the future. As a concrete example, one iOS release already skipped a Darwin release; the same could happen with OS X.Arrhythmia
S
26

There is the NSAppKitVersionNumber value which you can use to check the various versions of AppKit, although they don't correspond exactly to OS versions

if (NSAppKitVersionNumber <= NSAppKitVersionNumber10_7_2) {
    NSLog (@"We are not running on Mountain Lion");
}
Stalemate answered 28/7, 2012 at 0:45 Comment(1)
This is also implied by official documentation here (under point 'Runtime Version Check'): developer.apple.com/library/mac/#releasenotes/Cocoa/AppKit.htmlBismuthinite
A
20

There is a cocoa API. You can get an os X version string from the class NSProcessInfo.

The code to get the operating System Version String is below..

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

NSLog(@"operatingSystemVersionString => %@" , operatingSystemVersionString);

// ===>> Version 10.8.2 (Build 12C2034) result value

It isn't deprecated.

Agnosia answered 5/6, 2013 at 8:44 Comment(4)
10.10 adds a way to fetch it in a structured way (quite literally), but you can only use it if you're targeting the 10.10 SDK. Which rather defeats the purpose, at the moment. You can still use Gestalt() for now, but it's deprecated and could disappear at any moment.Pu
This COULD be great. It's not deprecated and works on 10.2+ sdk... Unfortunately the Apple documentation says The operating system version string is human readable, localized, and is appropriate for displaying to the user. This string is not appropriate for parsing. developer.apple.com/reference/foundation/nsprocessinfo/…Gender
The answer from @Vikas Bansal is arguably better.Gender
Downvoted because it requires parsing of a user-presentable text that may change in the future in unexpected ways! It's good for showing to the user, but not for the task the question is about, i.e. making decisions in code depending on the OS version.Emaciated
S
12

There is also kCFCoreFoundationVersionNumber which can be used if you only need to check for a minimum version to support. This has the advantage that it works going back to 10.1 and can be done in C, C++, and Objective-C.

For example to check for 10.10 or greater:

#include <CoreFoundation/CoreFoundation.h>
if (floor(kCFCoreFoundationVersionNumber) > kCFCoreFoundationVersionNumber10_9) {
    printf("On 10.10 or greater.");
}

You will need to link with the CoreFoundation (or Foundation) framework.

It also works in Swift in the exact same way. Here's another example:

import Foundation
if floor(kCFCoreFoundationVersionNumber) > kCFCoreFoundationVersionNumber10_8 {
    println("On 10.9 or greater.")
} else if floor(kCFCoreFoundationVersionNumber) > kCFCoreFoundationVersionNumber10_9 {
    println("On 10.10 or greater.")
}
Sward answered 24/10, 2014 at 15:21 Comment(6)
Thanks, this is nice, and quite exactly what I was looking for - no need for Appkit (linking against Obj-C code and runtime), no need for system calls, file reads, and so on --- simple constant maintained by the OS. One thing though - what header should be included for this constant to be available?Cardoso
@MottiShneor I added the necessary #include and link info.Sward
Thanks! perfect now :) I think someone (hmmm... me?) should summarize all the options, (not to few I'm sorry to say) and explain which is best in which scenario. I must say I personally like the CoreFoundation thing best. However - if you're writing a unix-style daemon, with not even CoreFoundation linked... what do you do then? revert to sysctl() ?Cardoso
@MottiShneor Why wouldn't you link to CF on OS X? Easy with a platform specific project setting. Even linking with Foundation and using the Objective-C API is doable with C code, just wrap it in a C function.Sward
Are those kCFCoreFoundationVersionNumber10_XXX constants provided for versions newer than 10.10.3? This is the largest constant I find CFBase.h header of XCode 8.0.Canvas
Turns out the constants are available up to kCFCoreFoundationVersionNumber10_11 in the MacOSX10.12.sdk. Try grep kCFCoreFoundationVersionNumber10_ -R /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk You just need to make sure you use CoreFoundation headers from the SDK, not from the systemCanvas
S
11

You can easily get the major, minor, patch version of the Operating System using NSOperatingSystemVersion

NSOperatingSystemVersion version = [[NSProcessInfo processInfo] operatingSystemVersion];

NSString* major = [NSString stringWithFormat:@"%d", version.majorVersion];


NSString* minor = [NSString stringWithFormat:@"%d", version.minorVersion];


NSString* patch = [NSString stringWithFormat:@"%d", version.patchVersion];
Stardom answered 27/7, 2015 at 15:52 Comment(4)
OS X 10.10 and later only.Opposition
Best answer if you're ok with not having it until 10.10 as @Opposition points out.Gender
Is OS X 10.10 required at build time or on the machine running the application?Canvas
Downvoted because it requires parsing of a user-presentable text that may change in the future in unexpected ways!Emaciated
N
9

Or, to put it more simply, here is the code:

NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"];
NSString *productVersion = [version objectForKey:@"ProductVersion"];
NSLog (@"productVersion =========== %@", productVersion);

I hope this helps someone.

Nazler answered 22/2, 2013 at 15:13 Comment(2)
Thanks for your comment. What would be a work around this, so I may include in my answer?Nazler
Thanks, this worked well for an odd use case. I needed to know the version of macOS while running some iOS test cases on the iOS 11 simulator, in order to determine whether the HEVC/H265 codec is supported (iOS 11 theoretically supports it, but only if the simulator is running on macOS 10.13 or later).Corticosterone
L
9

Gestalt() is a pure C API. The accepted answer suggests using NSProcessInfo but that requires Objective-C code and cannot be used if pure C is a requirement for some reason. Same holds true for NSAppKitVersionNumber, which also isn't updated anymore by Apple since 10.13.4. Using the constant kCFCoreFoundationVersionNumber was possible in C code but this constant hasn't been updated anymore since 10.11.4. Reading kern.osrelease using sysctl is possible in C but requires a mapping table or relying on the current kernel versioning scheme and thus is not reliable for future version as the kernel version scheme might change and a mapping table cannot know future versions.

The official and recommend way from Apple is to read /System/Library/CoreServices/SystemVersion.plist as this is also where Gestalt() gets the version number from, this is also where NSProcessInfo() gets the version number from, this is also where the command line tool sw_vers gets the version number from and this is even where the new @available(macOS 10.x, ...) compiler feature gets the version number from (I diged deep into the system to find out about this). I wouldn't be surprised if even Swift's #available(macOS 10.x, *) would get the version number from there.

There is just no simple C call for reading the version number from there, so I wrote the following pure C code which only requires CoreFoundation framework that itself is pure C framework:

static bool versionOK;
static unsigned versions[3];
static dispatch_once_t onceToken;

static
void initMacOSVersion ( void * unused ) {
    // `Gestalt()` actually gets the system version from this file.
    // Even `if (@available(macOS 10.x, *))` gets the version from there.
    CFURLRef url = CFURLCreateWithFileSystemPath(
        NULL, CFSTR("/System/Library/CoreServices/SystemVersion.plist"),
        kCFURLPOSIXPathStyle, false);
    if (!url) return;

    CFReadStreamRef readStr = CFReadStreamCreateWithFile(NULL, url);
    CFRelease(url);
    if (!readStr) return;

    if (!CFReadStreamOpen(readStr)) {
        CFRelease(readStr);
        return;
    }

    CFErrorRef outError = NULL;
    CFPropertyListRef propList = CFPropertyListCreateWithStream(
        NULL, readStr, 0, kCFPropertyListImmutable, NULL, &outError);
    CFRelease(readStr);
    if (!propList) {
        CFShow(outError);
        CFRelease(outError);
        return;
    }

    if (CFGetTypeID(propList) != CFDictionaryGetTypeID()) {
        CFRelease(propList);
        return;
    }

    CFDictionaryRef dict = propList;
    CFTypeRef ver = CFDictionaryGetValue(dict, CFSTR("ProductVersion"));
    if (ver) CFRetain(ver);
    CFRelease(dict);
    if (!ver) return;

    if (CFGetTypeID(ver) != CFStringGetTypeID()) {
        CFRelease(ver);
        return;
    }

    CFStringRef verStr = ver;
    // `1 +` for the terminating NUL (\0) character
    CFIndex size = 1 + CFStringGetMaximumSizeForEncoding(
        CFStringGetLength(verStr), kCFStringEncodingASCII);
    // `calloc` initializes the memory with all zero (all \0)
    char * cstr = calloc(1, size);
    if (!cstr) {
        CFRelease(verStr);
        return;
    }

    CFStringGetBytes(ver, CFRangeMake(0, CFStringGetLength(verStr)),
        kCFStringEncodingASCII, '?', false, (UInt8 *)cstr, size, NULL);
    CFRelease(verStr);

    printf("%s\n", cstr);

    int scans = sscanf(cstr, "%u.%u.%u",
        &versions[0], &versions[1], &versions[2]);
    free(cstr);
    // There may only be two values, but only one is definitely wrong.
    // As `version` is `static`, its zero initialized.
    versionOK = (scans >= 2);
}


static
bool macOSVersion (
    unsigned *_Nullable outMajor,
    unsigned *_Nullable outMinor,
    unsigned *_Nullable outBugfix
) {
    dispatch_once_f(&onceToken, NULL, &initMacOSVersion);
    if (versionOK) {
        if (outMajor) *outMajor = versions[0];
        if (outMinor) *outMinor = versions[1];
        if (outBugfix) *outBugfix = versions[2];
    }
    return versionOK;
}

The reason for using a dispatch_once_f instead of dispatch_once is that blocks aren't pure C either. The reason for using dispatch_once at all is that the version number cannot change while the system is running, so there is no reason for reading the version number more than once during a single app run. Also reading it is not guaranteed to be fail-safe and too expensive to re-read it every time your app may require it.

Talking about not being fail-safe, even though it is unlikely, reading it may, of course, fail, in which case the function returns false and always will return false. I leave it up to you to handle that case in a meaningful way in your app code because I cannot know how critical knowing the version number is to your app. If the version number is not critical, maybe you can work around it, otherwise you should make your app fail in a user friendly way.

Note
If you only require the version number to execute alternative code depending on the system version, there might be a better alternative to querying the version number on your own. See this question for details.

Liberec answered 1/6, 2019 at 1:3 Comment(0)
W
8

If you have an app that needs to run on 10.10 as well as prior versions, here's a solution:

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

if ([[NSProcessInfo processInfo] respondsToSelector:@selector(operatingSystemVersion)]) {
    MyOperatingSystemVersion version = ((MyOperatingSystemVersion(*)(id, SEL))objc_msgSend_stret)([NSProcessInfo processInfo], @selector(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
}

Note that even 10.9 seems to respond to the operatingSystemVersion selector, so I think it just was a private API in 10.9 (but still works).

This works on all versions of OS X and doesn't rely on string parsing or file I/O.

Wilma answered 12/8, 2014 at 13:32 Comment(4)
Do NOT use gestaltSystemVersion! This will fail if any version component is greater than 9. For example, OS X 10.4.11 would be returned as 10.4.9. Instead, retrieve each version component individually using gestaltSystemVersionMajor, gestaltSystemVersionMinor, and gestaltSystemVersionBugFix.Arrhythmia
Just FYI, this still does rely on file I/O internally... both methods will read SystemVersion.plist each time they are called (no caching).Arrhythmia
For some reason, doing the respondsToSelector check on operatingSystemVersion returns YES even though I'm on Mavericks.Bayless
To use operatingSystemVersion what should be the OS X SDK version? I am using Xcode 4.4.6 and SDK is OS X 10.8. Can I use it with this SDK or I need to install latest XcodeVantage
C
8

This is actually a compilation of answers above, with some further guiding to the developer in need.

OS-X provides its version in runtime in several ways. Each way fits better to specific development scenario. I'll try to summarise them all, and hope that others will complete my answer if I forgot something.

First, the comprehensive list of ways to obtain the OS version.

  1. The uname command-line tool and function provides the unix (darwin) version of the OS. Although this is not the marketing version of the OS, it is aligned with it uniquely, so you can deduce the OS-X marketing version from it.
  2. sysctl kern.osrelease command line (or sysctlbyname("kern.osrelease", str, &size, NULL, 0) function) will provide the same information as uname, marginally easier to parse.
  3. Gestalt(gestaltSystemVersionMajor) (with its "Minor" and BugFix" variants is the oldest (pre-Carbon!) API to get the marketing OS version, still supported by long deprecated. Available in C from the CoreServices framework, but not recommended.
  4. NSAppKitVersionNumber is a float constant of the AppKit framework, that will provide the OS-X Appkit version (aligned with the OS version), available to all applications which link against AppKit. It also provides a comprehensive enumeration of all possible versions (e.g. NSAppKitVersionNumber10_7_2)
  5. kCFCoreFoundationVersionNumber is a CoreFoundation framework float constant, identical to the Appkit counterpart, available to all apps linked against CoreFoundation, in both C, Obj-C and Swift. It, too provides a comprehensive enumeration over all OS X released versions (e.g. kCFCoreFoundationVersionNumber10_9)
  6. [[NSProcessInfo processInfo] operatingSystemVersionString]; is a Cocoa API available in Obj-C to both OS-X and iOS applications.
  7. There is a resource .plist in /System/Library/CoreServices/SystemVersion.plist which among other things, contains the OS version in the "ProductVersion" key. NSProcessInfo reads its information from this file, but you can do this directly using your PList-reading API of choice.

For more details on each option - please consult the answers above. There's plenty of information there!

Cardoso answered 18/4, 2016 at 9:55 Comment(2)
Number 5 is not updated anymore. Even in 10.13 the latest define is for kCFCoreFoundationVersionNumber10_11_Max, so no defines for 10.12 and 10.13 can be found there.Liberec
Now #4 which I liked the most has ceased to update too - the latest value is NSAppKitVersionNumber10_12_2 on MacOS SDK 10.13. Shame.Cardoso
C
6

There's uname(3):

The uname() function stores nul-terminated strings of information identifying the current system into the structure referenced by name.

The utsname structure is defined in the <sys/utsname.h> header file, and contains the following members:

  • sysname - Name of the operating system implementation.
  • nodename - Network name of this machine.
  • release - Release level of the operating system.
  • version - Version level of the operating system.
  • machine - Machine hardware platform.
Chiromancy answered 17/6, 2012 at 16:24 Comment(7)
This doesn't actually work, as uname() returns the version of the kernel, not the marketing version (e.g. "10.8".)Sclaff
Yes, Jonathan is right. I tried this and it is reporting: release: "12.0.0", version: "Darwin Kernel Version 12.0.0: Thu Jun 7 18:47:37 PDT 2012; root:xnu-2050.6.71~1/RELEASE_X86_64"Antiscorbutic
uname() is really useful for getting the mobile device model (e.g. "iPad2,1") though, so... it isn't completely useless. :)Sclaff
Isn't there a 1:1 mapping between the kernel and marketing versions?Chiromancy
Yes, but it's not a linear relationship. There's no way to translate between the two, and the kernel version is meaningless to the user and your QA department.Sclaff
@JonathanGrynspan: It is mostly linear. The Darwin major version is 4 versions ahead of the OS X minor version (e.g. 10.4 is Darwin 8, 10.6 is Darwin 10, 10.8 is Darwin 12). The darwin minor version is the same as the Gestalt "bug fix". For example, my system is running 10.8.2 and my kernel version is 12.2. On my 10.4.11 system the kernel version is 8.11. My 10.5.8 box is also Darwin 9.8.Gaslight
Mostly linear is not good enough. Note that iOS skipped one version of Darwin so far (13, I think), and that could just as well happen in the future with OS X.Arrhythmia
B
6

This is what I use:

NSInteger osxVersion;
if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_6) {
    //10.6.x or earlier systems
    osxVersion = 106;
    NSLog(@"Mac OSX Snow Leopard");
} else if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_7) {
    /* On a 10.7 - 10.7.x system */
    osxVersion = 107;
    NSLog(@"Mac OSX Lion");
} else if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_8) {
    /* On a 10.8 - 10.8.x system */
    osxVersion = 108;
    NSLog(@"Mac OSX Moutain Lion");
} else {
    /* 10.9 or later system */
    osxVersion = 109;
    NSLog(@"Mac OSX: Mavericks or Later");
}

It is recommended in AppKit Release Notes

Reading /System/Library/CoreServices/SystemVersion.plist is not possible if the app is sandboxed

Baughman answered 6/3, 2014 at 13:15 Comment(1)
"Reading /System/Library/CoreServices/SystemVersion.plist is not possible if the app is sandboxed" - this is NOT correct. According to the Apple documentation and my own experience, sandboxed applications have access to world-readable items in /System. See developer.apple.com/library/mac/documentation/security/…Arrhythmia
P
6

While playing around with sysctl on macOS today I stumbled upon kern.osproductversion which indeed contains the current OS version. On my Mac running Mojave I get:

$ sysctl kern.osproductversion
kern.osproductversion: 10.14.3

The value can be retrieved programmatically as well, of course:

char str[256];
size_t size = sizeof(str);
int ret = sysctlbyname("kern.osproductversion", str, &size, NULL, 0);

This commit to the xnu kernel code base indicates that osproductversion is a recent addition that came in mid 2018. I successfully tested it on 10.14.3 and 10.13.6.

All in all, the best programmatic, non-Cocoa approach in my opinion would be to check if kern.osproductversion produces a valid result and fall back to kern.osrelease and manual mapping as described in this answer otherwise.

Parakeet answered 1/2, 2019 at 19:54 Comment(0)
C
2

Late to the game, but I ended up here looking for an answer as well. For what it's worth, maybe it's of use for someone else;

In the past I used the command-line approach:

sw_vers

Which results in:

ProductName:    Mac OS X
ProductVersion: 10.13.6
BuildVersion:   17G65

Each line can be asked for individually (mind the camelback notation):

sw_vers -productVersion
10.13.6

sw_vers -productName
Mac OS X

sw_vers -buildVersion
17G65

Having said that, thanks for all the other solutions listed here ...

Clearly answered 14/8, 2018 at 17:27 Comment(0)
D
0

//my two cents for Swift (Multiplatform)

#if os(iOS)
import UIKit
#elseif os(OSX)
import Cocoa
#endif



func platform() -> String {
    var systemInfo = utsname()
    uname(&systemInfo)
    let size = Int(_SYS_NAMELEN) // is 32, but posix AND its init is 256....
    
    let s = withUnsafeMutablePointer(to: &systemInfo.machine) {p in
        //    let s = withUnsafeMutablePointer(to: &systemInfo.nodename) {p in
        
        p.withMemoryRebound(to: CChar.self, capacity: size, {p2 in
            return String(cString: p2)
        })
        
    }
    return s
}



func AppName()->String{
    let bund = Bundle.main
    if let displayName = bund.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String {
        if displayName.count>0{
            return displayName
        }
    }
    
    if let name = bund.object(forInfoDictionaryKey: "CFBundleName") as? String {
        return name
    }
    return "no AppName"
}


func buildVers()->String{
    
    let bund = Bundle.main
    let vers = bund.object(forInfoDictionaryKey: "CFBundleVersion") as! String
    return  vers
}


func AppleStoreVers()->String{
    
    if let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
        return version
    }
    return "no.vers."
}



#if os(iOS)
func systemVersion()->String{
    let  v = UIDevice.current.systemVersion
    return v
}
#elseif os(OSX)
#endif
Ducktail answered 22/8, 2020 at 17:43 Comment(0)
H
0

2022, MacOS

let a = ProcessInfo.processInfo.operatingSystemVersion

let b = ProcessInfo.processInfo.operatingSystemVersionString

iOS:

var a = UIDevice.current.systemVersion

let b = ProcessInfo.processInfo.operatingSystemVersion

let c = ProcessInfo.processInfo.operatingSystemVersionString
Hyetograph answered 15/12, 2022 at 14:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.