Mac How to use framework from 10.6 SDK conditionally?

frankpuccino

macrumors newbie
Original poster
Jul 24, 2010
29
0
I'm deploying a Mac OS X desktop application for
Intel machines running 10.5 or 10.6.

Apple introduced a new framework in 10.6 and
when I target my app to 10.6, everything works
perfectly.

The framework is not present in 10.5 and I'd
like to have a reduced functionality version for
10.5.

Can somebody suggest how I can produce a
single binary that will run under both 10.5 and
10.6 and allow me to use the new framework
if the user is running 10.6?

I sort of need the Mac OS X equivalent of
"LoadLibraryA" in Windows.

Thank you.
 

Thomas Harte

macrumors 6502
Nov 30, 2005
396
2
Catfish_Man gives the correct answer. If you weak link against a framework then:

  • if the framework exists, its symbols will be loaded and available as per the standard runtime linking rules;
  • if it doesn't, its symbols won't be loaded but your program will still run.

To weak link, select your target from the relevant folder in Xcode then look at the list of 'Linked Libraries' over in the detail disclosure (or perform 'Get Info' on the target if you use the condensed Xcode layout as I do) and change the value in the 'Type' column from 'Required' to 'Weak'.

The only slight gotcha is that if you have code later on that does something like this:

Code:
ClassName *newInstance = [[ClassName alloc] init];
(ie, standard allocation pattern — ask the metaclass to alloc you an instance, ask the instance to init itself)

And ClassName doesn't exist in the runtime (eg, because it is defined in a weakly linked library but the library doesn't exist so wasn't loaded) then your program will raise an exception and exit. The trivial workaround is:

Code:
ClassName *newInstance = [[NSClassFromString(@"ClassName") alloc] init];
NSClassFromString gets a class from the runtime if it exists or returns nil if it doesn't. So if the class doesn't exist, you'll call alloc on a nil class, resulting in nil (as per any selector sent to a nil class) then init on another nil class, resulting in newInstance being nil.

If the class does exist, then you'll get an instance of it, assuming init succeeds.

And obviously you can just use NSClassFromString(...) != nil to test whether classes exist and run down different routes of normal [[ClassName alloc] inits] if you prefer.
 

gnasher729

macrumors P6
Nov 25, 2005
16,599
3,219
Set deployment target = 10.5 and SDK = 10.6.

Whenever you want to use a C function that you think might not be available, just check whether its address is a null pointer. Whenever you want to call a method that you think might not be available, well there is an NSObject method that you can call to check whether any selector is supported by an object. Can't think of the name right now, check the NSObject docs.
 

frankpuccino

macrumors newbie
Original poster
Jul 24, 2010
29
0
I want to thank everybody who replied in this thread!

gnasher729, I'm using Xcode 3.2.2. I'm probably a couple of versions behind.

Do you mean that I have 10.5 as the "Base SDK" and set 10.6 to be the "Active SDK"?

Thank you.

Frank
 

gnasher729

macrumors P6
Nov 25, 2005
16,599
3,219
I want to thank everybody who replied in this thread!

gnasher729, I'm using Xcode 3.2.2. I'm probably a couple of versions behind.

Do you mean that I have 10.5 as the "Base SDK" and set 10.6 to be the "Active SDK"?

Thank you.

Frank
Click on your Target, Info, -> Look for "MacOS X Deployment Target". Deployment target = lowest version of the OS that is allowed to run your code. If you want to run on 10.5 and 10.6 but not 10.4 then set the deployment target to 10.5.

Base SDK should be 10.6 so all the interfaces are available to your code; you can't call anything that is new in 10.6 unless you use the 10.6 SDK.