Making an app backwards compatible, problems with frameworks - macos

I've been having some trouble making my app backward compatible for Mac OS X 10.6 systems. I've integrated Crashlytics into the app and it works fine for Mac OS X 10.7 - 10.10 and it works just fine. However, the app also needs to be compatible with the older version of OS X 10.6 and the Crashlytics framework only supports down to 10.7.
I already fixed the first crash due to the libc++ library which did not come bundled with 10.6 by making it an optional include. It's the next crash I can't figure out: Symbol not found: _objc_release
If I completely remove all calls to Crashlytics inside the app it works just fine. However, if I include the one line which Crashlytics needs to get started: [Fabric with:#[[Crashlytics class]]]; it will crash right after launching with Symbol not found: _objc_release.
The next logical step for me was to add a simple if statement to check if the system version was compatible with the framework, but the app still crashed although if I removed the Crashlytics line the if statement worked just fine!
I'm using Xcode 7, Mac OS X 10.10 with the base SDK set to 10.6.
Here is a quick example of what I have tried:
Using the suggested way by Apple:
Class cls = NSClassFromString(#"Fabric");
if(!cls)
{
[Fabric with:#[[Crashlytics class]]];
NSLog(#"Framework is installed!");
}
else
{
NSLog(#"Framework is not installed!");
}
Comparing System version numbers:
if(NSAppKitVersionNumber >= NSAppKitVersionNumber10_7)
{
[Fabric with:#[[Crashlytics class]]];
NSLog(#"Framework is installed!");
}
else
{
NSLog(#"Framework is not installed!");
}
Am I missing something obvious here?

Related

Mac App Backwards Compatible to Yosemite

I'm on El Capitan in XCode 7.3.1 and Swift 2 trying to make my mac application work on Yosemite (it just doesn't open at all with no crash logs).
I have 10.10 set as the deployment target, but that didn't change anything.
I downloaded Xcode 6.4 on another machine and loaded the project and it's complaining a ton about all of my swift code not being a thing.
I'm assuming (hoping) I don't have to figure out how to write this in an old version of Swift in order to make it work on Yosemite.
How do I know which features of the new SDK need to be made backwards compatible?

Xcode-beta and updated/new frameworks

I run Xcode-beta 7 on 10.10.3. It has new GameplayKit framework and updated SceneKit framework. Can I use them (or their new features) in my current project, or I must have 10.11 beta?
You can write your code on OS X 10.10.3 using Xcode 7β. You can even compile and export the app since Xcode can build it against the included 10.11 SDKs.
You can not, however, run the app on your Mac under 10.10.3. For the app to run you need to update to 10.11β.
Make sure to
always use the same beta version for Xcode and OS X
always use the latest beta
If you try to run an app that links against an SDK that is not available your app will crash before it even started with an error similar to
dyld: Library not loaded: /System/Library/Frameworks/Metal.framework/Versions/A/Metal
That is because the app is configured to tell dyld to search in the system's Frameworks directory for the framework and that directory does not contain the framework on your version of OS X.
For unknown symbols in existing (updated) frameworks there are two options depending on the language:
Swift: With Swift 2.0 the compiler automatically warns you that the API you want to use is not available and makes you guard that statement like so:
if #available(OSX 10.11, *) {
let nameComponents = NSPersonNameComponents()
} else {
// Fallback on earlier versions
}
Objc: Use this answer.

How do you debug an app for an older version of Mac OS X?

I am developing an app using Xcode 4.6 on an OS X 10.8 machine. The app deployment target is set to 10.6, which is what we need to support. But when I archive the app (compile, link and embed resources+frameworks) and deploy (aka copy) it to the 10.6 test machine, it crashes with a generic Segmentation fault. It works fine on 10.7.
I can't compile the project in Xcode on the older Mac because the app is built using the newer compiler (it uses ARC, implicit property synthesis, the new objective-c literal syntax, etc.). It also wouldn't type check because the base SDK is 10.8 and it references some 10.8 tokens which the compiler on the 10.6 machine doesn't know about.
Any suggestions on how to go about debugging the app?
I'm not affiliated with this company/software in any way, but Deploymate is a paid app which can scan your app for SDK usage and tell you when you are calling selectors and APIs that are unavailable on older OS versions. This can help you track down exceptions and crashes relating to API usage.
You are very likely using one or more 10.7+ APIs that crash on 10.6. With a 10.8 target SDK you allow all the calls to function that are available in that SDK. However apps are bound late so this doesn't crash when you do not actually call those functions. You need an explicit check similar to this (here for the full screen feature):
#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_6
if (runningOnLionOrLater) {
[mainWindow setCollectionBehavior: NSWindowCollectionBehaviorFullScreenPrimary];
[toggleFullscreenItem setHidden: NO];
}
#endif
One way to determine the current version is:
int macVersion;
if (Gestalt(gestaltSystemVersion, &macVersion) == noErr) {
runningOnLionOrLater = macVersion > MAC_OS_X_VERSION_10_6;
}
For debugging the problematic calls simply set the base SDK to 10.6 and XCode should mark those functions that are not available there.
While there is no real good solution to this (I've seen simply different behaviors on different macOS versions) and no way to simply simulate an older macOS version, if you have a machine to spare:
It is possible to use an external HD, partition it and install different macOS versions. They all can be bootable and it's a matter (pain) of restarting the machine for every OS version.

OS X App - deployment target set to 10.6 in Xcode, but app only runs on 10.7

I've just discovered that my current version of the app doesn't launch on 10.6.
It used to work fine in 10.6 before. So I must have changed something in recent versions. So before I dive in and start comparing the source codes, is there a way to find out what cause the app not to launch in 10.6 but works fine in 10.7.
Details:
Xcode 4.3
LLVM compiler 3.1
Deployment target set to 10.6
Also, would Xcode warn me if I'm using a 10.7-only API in my code?

XCode Mac OS X compatibility setting

I just created a small program in XCode 4 for Mac OS X. I want it to run on 10.4, 10.5 and 10.6. How can I do that? I am currently running Snow Leopard. In XCode 4, if I click my project, there's a settings for deployment Target, which is a drop down list and I can only select 1 of : 10.4, 10.5 or 10.6. How can I make sure it is compatible with all of them? Thanks.
The deployment target is the minimum version you want to be compatible with. Set it to 10.4.
Since you have to use the 10.6 SDK with Xcode 4, you’re responsible for making sure you don’t use any APIs that aren’t available in 10.4 without testing for them first. You also can’t build PowerPC-compatible apps with Xcode 4.
build with 10.4
You will also want to build it in 10.6 also to make sure that you aren't using anything that has or will become deprecated... warnings will be thing that will become deprecated, errors will already be deprecated, you may have to do some conditional compilation. to keep things straight.
#if MAC_OS_X_VERSION_MIN_REQUIRED == MAC_OS_X_VERSION_10_4
//do something using 10.4 code
#elsif MAC_OS_X_VERSION_MIN_REQUIRED == MAC_OS_X_VERSION_10_5
//do something using 10.5 code
#else
//do something using 10.6+ code
#endif

Resources