views:

312

answers:

2

I'm trying to upgrade an app (Clarke) to provide 10.6 compatibility.

My plan is to use two different code paths depending on the version of OSX in use.

On 10.5 it will use one controller, which consists of completely custom code that isn't dependent on any specific Cocoa API. On 10.6 it will use another controller, which wraps the new CoreLocation API in an identical interface, based on the same abstract class. At runtime the app will switch between the controllers by detecting the OS version.

This works fine on 10.6 built for the 10.6 SDK, but the same build blows up on 10.5 with:

10/09/2009 18:30:50 [0x0-0x12f12f].uk.co.tomtaylor.Clarke[4575] dyld: unknown required load command 0x80000022 
10/09/2009 18:30:51 com.apple.launchd[403] ([0x0-0x12f12f].uk.co.tomtaylor.Clarke[4575]) Exited abnormally: Trace/BPT trap

If I build for 10.5 SDK it can't compile the CoreLocation stuff, obviously.

I'd hoped to be able to provide a single binary for this application. Is there a way to 'hide' the CoreLocation API from 10.5?

+4  A: 

You should be able to solve this problem by changing the build settings of your target:

  1. Set the Base SDK to 10.6
  2. Set the Deployment SDK to 10.5
Markus Müller
This is the correct method but there is more to it:When you need to call APIs that are in 10.6 but not 10.5 you need to get the class name using NSClassFromString(). Then check whether or not the class name returned is valid. If it's valid, you can go ahead and call the APIs you need. If not, you'll need to fail-over gracefully.
Jasarien
+5  A: 

The Deployment SDK trick works only when you have the same framework on both platforms but new calls in the newer one. For CoreLocation, the entire framework is missing on 10.5, so your app will fail to load because it cannot dynamically bind to the framework.

You need to do the above, plus add CoreLocation as a weak framework. Select your Link Frameworks and Binaries build phase, find CoreLocation in the Detail view, and in the middle column change "Required" to "Weak".

When you build your app, Xcode will pass -weak_framework CoreLocation to the linker, and your app will load on all 10.5 and 10.6 systems regardless of whether CoreLocation is present. It's up to you to make sure not to call any CoreLocation methods unless you are actually running on 10.6, though.

cdespinosa
It's -weak_framework, rather than -weak-framework
AlBlue