If your code requires a feature that is only available in macOS 10.12 or newer, but you want your code to also deploy to earlier system versions, you can use @available
in Objective-C:
if (@available(macOS 10.12, *)) {
// Code that requires 10.12 APIs
} else {
// Code that doesn't require 10.12 APIs
}
You can do the same thing in Swift using #available
:
if #available(macOS 10.12, *) {
// Code that requires 10.12 APIs
} else {
// Code that doesn't require 10.12 APIs
}
But what can you use if you write C or C++ code?
You can use Objective-C and Swift files together in a single project, no matter which language the project used originally. This makes creating mixed-language app and framework targets as straightforward as creating an app or framework target written in a single language.
Swift is a general-purpose, high-level programming language which is highly concerned about safety, performance. Objective C is an general purpose language which is considered as superset of C language it was designed in an aim of providing object-oriented capabilities.
Swift has better memory management features than Objective-C, which can help improve performance. It uses lazy initialization, reducing memory usage since unused variables do not initialize—making it faster, easier to read and write, and safer.
C++ compatibility It is incredibly easy to implement C++ code into an Obj-C project, which is one of the major advantages of Objective C over Swift. Considering the great number of programmers working with C++, this level of compatibility makes the language very appealing to a large audience.
In C and C++ you can use the Clang compiler extension __builtin_available
:
if (__builtin_available(macOS 10.12, *)) {
// Code that requires 10.12 APIs
} else {
// Code that doesn't require 10.12 APIs
}
That is if you have at least Clang 5 available (Xcode 5.0 or newer).
Keep in mind that you will have to set a deployment target to make this feature work correctly (e.g. -mmacosx-version-min=10.9
). The reason is that the linker requires this information to decide when to perform weak linking. Setting the deployment target to 10.9 for example tells the linker that if your code is using any symbols that were not already available in 10.9, these symbols must be weakly linked.
Normally an executable or library will try to resolve all referenced symbols at load and fail to load if any such symbol cannot be found. However, when a symbol is weakly linked, being unable to resolve a symbol will not cause loading to fail, instead any reference to that symbol becomes a NULL
reference at runtime. Needless to say, if you try to call a function that was weakly linked and has not been found at load, your app will crash (you are trying to call NULL
as a function). And that's where __builtin_available
comes to the rescue.
if (__builtin_available(macOS 10.12, *)) {
// ...
} else {
// Symbols only available in 10.12 or newer are all NULL when
// you reach this code block but you wouldn't use any of them
// in this code block, would you? So, no problem.
}
If you don't use -mmacosx-version-min
, the __builtin_available
construct will still work correctly, yet as the linker doesn't know what system you are targeting, it assumes the current system and won't perform any weak linking. If you then try to run your app on an earlier system version, some symbols won't be found and your app even refuses to load, despite the fact that it would have alternative code paths for that system.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With