Deployment Target and Different OSXs - xcode

here is my dev/project settings:
Deployment Target - 10.6
SDK: 10.9
Architecture: Universal 32/64.
Now when I archive and try to run it on ML 10.8 (other machine not my dev machine); It crashes and gives me "Classic environment is o longer supported" error.
I have not tested it yet on 10.6 though but what is the best way to keep my app running fine on all of them 10.6+ ?
Also I am using ASIHTTP and setting it to "-fno-objc-arc" in build-phases.
Please help.
I have set my project's Deployment Target to 10.6 to support older machines.

The Classic environment is no longer supported shouldn't be occurring based on the information your provide, as that refers to code written for OS 9, not OS X. However, based off of my own experience (this question), besides setting the deployment target to 10.6, you must also turn off base internationalization and auto layout for your NIBs. Good luck!

Related

Testing cocoa app targeted for multiple plaforms

I am new to cocoa and os x. I have developed an application that is meant for 10.5 and above. I have got 10.7 os x with me. Is there a way to simulate the testing without having to have real machines ? or atleast find as to at which places I am calling cocoa api which might not be available on any of the supported platforms ?
Thanks,
If you have the access you could install VMWare Fusion and load different versions of OSX into the VM to test the application.
You could also go into your build settings and set OS X Deployment Target to different versions of OS X. This would at least see if your application would build using that versions compiler.

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.

confusion of how to make osx app backward compatible & how to test them

after reading the apple SDK guide
https://developer.apple.com/library/mac/#documentation/developertools/conceptual/cross_development/Overview/overview.html
I'm still confused of how to make the mac app backward compatible & how to test them properly
I have an app, I run it and tested it on Mountain Lion 10.8 without any problem, however I want to make this app backward compatible so that other users can run it on a mac 10.6 - 10.7 machine.
I have an apple developer id and I can download the old versions of 10.7 and 10.6, but the problem is, I have a 2011 macbook air which is currently running 10.8, and that's the only apple machine that I have. Can I test the 10.7 and 10.6 by using vmware or parallels?
in my project settings, I set the target deployment to 10.6 (as I want 10.6 users to run my app), but should I set my SDK to 10.8 or 10.7? if I set the SDK to 10.8 but having the target deployment set to 10.6, if I fix all the xcode warnings will it run successfully on 10.6??
from the SDK drop down, I can only set to 10.8 or 10.7, but 10.6 is missing, how do I fix that?
thanks in advance
I develop on a 10.8 box and support back to 10.5. Just a couple of months ago we dropped 10.4 PPC support, and I'm still cleaning out some of the 10.2-specific code. This may get a little rant-y, but I've been doing old versions for a long time. I have some opinions on the matter.
No matter what Apple says in their docs, if you want to support 10.6, then build with the 10.6 SDK. Do not rely on distribution target.
I have had this discussion with the Xcode engineers, and while they hold to Apple's party line that you should always build with the latest SDK, they also acknowledge that it's generally insane to do so. If you build against the 10.8 SDK and mark your deployment target at 10.6, you will get no warnings for using methods that do not exist on 10.6. The only way you will discover that you've used a nonexistent method is that it might give you strange bugs when run on 10.6. That's insane.
Remember, OS X doesn't crash when you send an unknown selector. It just aborts the current runloop. So the bugs are even harder to track down then on iOS, where it crashes the app.
Sure, you can do weak linking. Talk about dangerous.... Yes, there are a few times this is useful, but the compiler gives you no warning if you don't do it correctly. If I'm going to do weak linking like this, I go the other way, linking against the old SDK and copying the new function's prototype into my implementation. That way I have documentation of every function I think I'm going to weak-link.
Download the old SDKs and symlink them into your Xcode distribution.
Guard them jealously. Apple will try to delete them every time you upgrade Xcode. Make your own copies and stick them in /SDKs or somewhere else away from Xcode. I provide a script called fix-xcode to manage the symlinks automatically. Am I bitter at Apple for their relentless insistance on deleting my old SDKs? Yes, I am.
You can run 10.6 Server in a VM legally. You can run 10.7+ Desktop in a VM legally. These are good ways to test your code.
Or you can do what I do and have a small pile of old MacBooks each with two or three partitions on them that you reboot all the time.
Now that 10.7 comes from App Store, it's a little harder to make VMs. My strong recommendation is to snapshot your image immediately after install, and make a clean backup copy of it. You'll want to be able to clone that image from time to time when you need to get back to a "raw" machine.
Get in the habit of squirreling away SDKs as they come out. 10.8 will be old some day. You might as well make a copy now while it's easy.
Whether you support individual dot-releases or not, it can be very helpful to keep around the upgrade packages for individual dot releases. When you encounter customers running non-current releases, it's nice to be able to check whether an "unreproducible" bug in fact is easily reproducible on their specific version. Whether this is worth it or not depends heavily on your product and customers. It was a life-saver for me when 10.4.11 made major changes to WebKit during a dot release...
Invest in a small NAS or a big external USB drive (though I've had trouble with those failing when used extensively, so I prefer a RAID). You'll need the space. You want to hold onto lots of VMs and lots of SDKs and sometimes even old versions of Xcode.
Adding to Rob Napier's great in-depth answer:
To use an old SDK, put the SDK (or a symlink) to it here:
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs
With XCode 7.3 or later, you need you to open this file and change "MinimumSDKVersion" (otherwise XCode will refuse to use the old SDK):
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Info.plist
You can install multiple versions of Mac OS on a single machine, booting between each.
The SDK should be the latest (10.8).
See 2.
One alternative to 1 that I've considered (I am in the same boat) is to create a Snow Leopard Hackintosh using an old PC and just installing Lion and Mountain Lion on my MBP.
You need to do these settings :
1.Set the Base SDK to Current version of Mac (ex. 10.7)
2.Set the Deployment SDK to older version (ex.1.4)

How to avoid XCode framework weak-linking problems?

I'm building an application that takes advantage of Mac OS X 10.6-only technologies, but without giving up backwards compatibility to 10.5 Leopard.
The way I do this is by setting the 10.6 SDK as the base SDK, weak-linking all frameworks and setting the deployment target to 10.5 as described in:
http://developer.apple.com/mac/library/DOCUMENTATION/MacOSX/Conceptual/BPFrameworks/Concepts/WeakLinking.html
This works fine; before making a call that is Snow Leopard-only I need to check that the selector or indeed the class actually exist. Or I can just check the OS version before making the call.
The problem is that this is incredibly fragile. If I make a single call that is 10.6 only I blow Leopard-compatibility. So using even the normal code code completion feature can be dangerous.
My question: is there any way of checking which calls are not defined on 10.5 before doing a release build? Some kind of static analysis, or even just a trick (a target set the other SDK?) would do.
I obviously should test on a Leopard machine before releasing anything, but even so I can't possibly go through all paths of the program before every release.
Any advice would be appreciated.
Best regards,
Frank
You could change the target SDK to 10.5. The compiler will then output warning: definition for '-snowLeopardOnlyMethod:' not found messages.

How do you enforce the minimum OS requirements in a Cocoa app?

My app needs to run on 10.4 or later. If I launch it on 10.3 it just fails to launch or crashes.
How do you tactfully enforce minimum system requirements? Can you customize the message it shows?
Add a key to your applications Info.plist, specifying LSMinimumSystemVersion as 10.4.X for whatever X you need as a minor version. For more, see Apple's documentation.
I have not used either of these techniques/advice, just passing along the information I have gathered.
You might try something like the SystemVersionCheck “shim” executable to provide a working OS version check for versions that do not honor LSMinimumSystemVersion (e.g. 10.3).
The pre-compiled executable is PPC-only. You might need to rebuild it to support PPC and Intel machines so that it works with 10.3, but also so that 10.6 users are not prompted to needlessly install Rosetta. I found a blog entry that has a hint on how to setup the PPC build to target 10.3 and the Intel build to target 10.4u (it was written about 10.5 and Xcode 3.0 though—do the latest versions of Xcode even include the 10.3 SDK?).
If you experience a crash after adding the LSMinimumSystemVersion key to your app's plist manually, then this is due to the Finder not recognizing the changed state of the app properly. Either restart the Finder (e.g. log out) or duplicate the app in the Finder. The copy will then behave correctly.

Resources