Xcode New API Usage Warning: SDK vs. Deployment Target

Update: This no longer works on Xcode SDK 10.10 due to changes by Apple to <Availability.h> If I find a new solution, I will update this post.

We know that Xcode warns us about deprecated API usage i.e. if we use an api in our code that was available in older versions of the OS X SDK but is now marked deprecated (and may disappear sometime in future) we get a warning. The warning is to let us know that we need to fix the deprecated API usage because in future when the API is removed, any reference to the API will result in BOOM!!! Cr@s*h**!!!. So far so good right.

But what happens when we want to support our app on older versions of OS X but we upgrade our Xcode which includes a newer OS X SDK. Let’s say we want to run our Mac app on OS X 10.7 (MACOSX_DEPLOYMENT_TARGET) onwards but the Xcode version we are using now for development comes with OS X 10.8 SDK. There are going to be certain new APIs (Methods / Classes / Enums) made available in 10.8. If we use these newer APIs in our code, the compilation will go on fine without Xcode giving any build warning about unavailability on 10.7 (MACOSX_DEPLOYMENT_TARGET) but when the app is run on OS X 10.7 and these new API symbols are referenced BOOM!!! Cr@s*h**!!!.

This leads us to our problem statement:

How do we generate warnings while using new API’s when our Deployment Target (Min OS X version we want to support) is lower than the Xcode SDK Version?

The original solution was given by Jeff Johnson here. The solution is to redefine certain <AvailabilityMacros.h> macros so that they start generating warnings when newer API’s are used. Adding the following code in our prefix header (.pch file) does the trick:

#ifdef __OBJC__
        
        #import <Foundation/NSObjCRuntime.h>
        
        #if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_7
            #undef  AVAILABLE_MAC_OS_X_VERSION_10_8_AND_LATER
            #ifdef __clang__
                #define AVAILABLE_MAC_OS_X_VERSION_10_8_AND_LATER __attribute__((weak_import, deprecated("API is newer than Deployment Target.")))
            #else
                #define AVAILABLE_MAC_OS_X_VERSION_10_8_AND_LATER WEAK_IMPORT_ATTRIBUTE
            #endif
        #endif
    
        #undef  NS_CLASS_AVAILABLE
        #define NS_CLASS_AVAILABLE(_mac, _ios) AVAILABLE_MAC_OS_X_VERSION_##_mac##_AND_LATER

        #undef  NS_ENUM_AVAILABLE
        #define NS_ENUM_AVAILABLE(_mac, _ios) AVAILABLE_MAC_OS_X_VERSION_##_mac##_AND_LATER

        #import <Cocoa/Cocoa.h>

#endif
  1. Redefining AVAILABLE_MAC_OS_X_VERSION_10_8_AND_LATER takes care of methods that are introduced in 10.8 which are marked as NS_AVAILABLE() or NS_AVAILABLE_MAC() in the headers.
  2. Redefining NS_CLASS_AVAILABLE takes care of classes that are introduced in 10.8 which are marked as NS_CLASS_AVAILABLE() or NS_CLASS_AVAILABLE_MAC() in the headers.
  3. Redefining NS_ENUM_AVAILABLE takes care of methods that are introduced in 10.8 which are marked as NS_ENUM_AVAILABLE() or NS_ENUM_AVAILABLE_MAC() in the headers.

We are generating warnings because we want to conditionally use the newer API’s when running on 10.8 after factoring in the non availability on 10.7. To suppress the warnings after factoring in the non-availability, we need to use #pragma directives as shown below:

Class notifCenter = NSClassFromString(@"NSUserNotificationCenter");
if(notifCenter){//NSUserNotificationCenter class available. This is the factoring in of non availability on 10.7.
     #pragma clang diagnostic push
     #pragma clang diagnostic ignored "-Wdeprecated-declarations"
        NSUserNotification *notification = [[[NSUserNotification alloc] init] autorelease];
        [notification setTitle:@"My Notification"];
        [NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];        
     #pragma clang diagnostic pop
}

Note: This solution needs to be modified when the MACOSX_DEPLOYMENT_TARGET and / or the SDK changes.


Related Readings:
Importance of order of #import, Weak Linking Symbols

Advertisements

One thought on “Xcode New API Usage Warning: SDK vs. Deployment Target

  1. Pingback: Order of #import and Xcode new api usage warnings | Sayeed Hussain On Technology

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s