How to use framework from 10.6 SDK conditionally?

Discussion in 'Mac Programming' started by frankpuccino, Jul 24, 2010.

  1. frankpuccino macrumors newbie

    Jul 24, 2010
    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

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

    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.
  2. Catfish_Man macrumors 68030


    Sep 13, 2001
    Portland, OR
    I don't have the documentation handy, but "weak linking" is the term to search for.
  3. Thomas Harte macrumors 6502

    Nov 30, 2005
    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:

    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:

    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.
  4. gnasher729 macrumors P6


    Nov 25, 2005
    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.
  5. frankpuccino thread starter macrumors newbie

    Jul 24, 2010
    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.

  6. gnasher729 macrumors P6


    Nov 25, 2005
    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.

Share This Page