1

There was a method for Xcode 4.x:

#define __AVAILABILITY_TOO_NEW __attribute__((deprecated("TOO NEW!"))) __attribute__((weak_import))

#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_6_0
#undef __AVAILABILITY_INTERNAL__IPHONE_6_0
#define __AVAILABILITY_INTERNAL__IPHONE_6_0 __AVAILABILITY_TOO_NEW
#endif

But that doesn't work anymore because the iOS 7 SDK Availability macros have changed and now have more variances and options:

iOS 6 SDK's AvailabilityInternal.h:

#define __AVAILABILITY_INTERNAL__IPHONE_6_0                    __attribute__((availability(ios,introduced=6.0)))
#define __AVAILABILITY_INTERNAL__IPHONE_6_0_DEP__IPHONE_6_0    __attribute__((availability(ios,introduced=6.0,deprecated=6.0)))
#define __AVAILABILITY_INTERNAL__IPHONE_6_0_DEP__IPHONE_6_1    __attribute__((availability(ios,introduced=6.0,deprecated=6.1)))
#define __AVAILABILITY_INTERNAL__IPHONE_6_0_DEP__IPHONE_NA     __attribute__((availability(ios,introduced=6.0)))

iOS 7 SDK:

#define __AVAILABILITY_INTERNAL__IPHONE_6_0                    __attribute__((availability(ios,introduced=6.0)))
#define __AVAILABILITY_INTERNAL__IPHONE_6_0_DEP__IPHONE_6_0    __attribute__((availability(ios,introduced=6.0,deprecated=6.0)))
#if __has_feature(attribute_availability_with_message)
     #define __AVAILABILITY_INTERNAL__IPHONE_6_0_DEP__IPHONE_6_0_MSG(_msg)    __attribute__((availability(ios,introduced=6.0,deprecated=6.0,message=_msg)))
#else
     #define __AVAILABILITY_INTERNAL__IPHONE_6_0_DEP__IPHONE_6_0_MSG(_msg)    __attribute__((availability(ios,introduced=6.0,deprecated=6.0)))
#endif
#define __AVAILABILITY_INTERNAL__IPHONE_6_0_DEP__IPHONE_6_1    __attribute__((availability(ios,introduced=6.0,deprecated=6.1)))
#if __has_feature(attribute_availability_with_message)
     #define __AVAILABILITY_INTERNAL__IPHONE_6_0_DEP__IPHONE_6_1_MSG(_msg)    __attribute__((availability(ios,introduced=6.0,deprecated=6.1,message=_msg)))
#else
     #define __AVAILABILITY_INTERNAL__IPHONE_6_0_DEP__IPHONE_6_1_MSG(_msg)    __attribute__((availability(ios,introduced=6.0,deprecated=6.1)))
#endif
#define __AVAILABILITY_INTERNAL__IPHONE_6_0_DEP__IPHONE_7_0    __attribute__((availability(ios,introduced=6.0,deprecated=7.0)))
#if __has_feature(attribute_availability_with_message)
     #define __AVAILABILITY_INTERNAL__IPHONE_6_0_DEP__IPHONE_7_0_MSG(_msg)    __attribute__((availability(ios,introduced=6.0,deprecated=7.0,message=_msg)))
#else
     #define __AVAILABILITY_INTERNAL__IPHONE_6_0_DEP__IPHONE_7_0_MSG(_msg)    __attribute__((availability(ios,introduced=6.0,deprecated=7.0)))
#endif
#define __AVAILABILITY_INTERNAL__IPHONE_6_0_DEP__IPHONE_NA               __attribute__((availability(ios,introduced=6.0)))
#define __AVAILABILITY_INTERNAL__IPHONE_6_0_DEP__IPHONE_NA_MSG(_msg)     __attribute__((availability(ios,introduced=6.0)))

Could it be that Xcode 5 has the attribute_availability_with_message feature so the old macro redefinition is no longer used?

Also it would be cool to print more than the "TOO NEW!" message with all the new introduced/deprecated information.

Edit:

Most definitions in iOS 7 SDK moved from __OSX_AVAILABLE_STARTING(_ios)/__AVAILABILITY_INTERNAL##_ios to NS_AVAILABLE_IOS(_ios)/CF_AVAILABLE_IOS(_ios), so redefining:

#undef NS_AVAILABLE_IOS
#define NS_AVAILABLE_IOS(_ios) __attribute__((availability(ios,__NSi_##_ios))) __attribute__((deprecated("TOO NEW!")))

Should work. And actually it does because Xcode 5 autocompletion shows the methods as deprecated.

Building however doesn't trigger any warning despite having the GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS build option on...

Community
  • 1
  • 1
Rivera
  • 10,792
  • 3
  • 58
  • 102
  • Is there a `__AVAILABILITY_INTERNAL__IPHONE_7_0` ? – borrrden Oct 01 '13 at 09:03
  • Then my answer might work. Try it out. – borrrden Oct 02 '13 at 05:36
  • It kinda works. See edit note. – Rivera Oct 02 '13 at 05:43
  • Try "unavailable" instead of "deprecated" for the attribute. – borrrden Oct 02 '13 at 05:47
  • First off I know now why Xcode doesn't trigger those deprecations warnings http://stackoverflow.com/questions/18197326/turn-deprecation-warnings-back-on. As for unavailable it has the same result. – Rivera Oct 02 '13 at 05:51
  • If you want warnings for too new APIs (i.e. you want to build for iOS 6) set your SDK to iOS 6 in Xcode settings. You won't be able to use any new APIs (except via soft linking). – nielsbot Oct 02 '13 at 07:27
  • @nielsbot: It works but then one has to import the iOS 6 SDK into Xcode 5 first. Also it shows up as an error and not a warning, so too many of them would stop the build. – Rivera Oct 02 '13 at 07:30
  • If you want your code to run on iOS 6, then any direct use of iOS 7 APIs _is_ an error. You have to write your code so that you do not use iOS 7 APIs. Yes--You will have to install the iOS 6 SDK. Depends if you're trying to make an iOS 6 compatible app or not. – nielsbot Oct 02 '13 at 18:49
  • @nielsbot Using newer API calls is not an error if you're careful to dynamically check the running version (`[[UIDevice currentDevice] systemVersion]`). – Rivera Oct 03 '13 at 01:32
  • Or when using e.g. `respondsToSelector:`... generally better than `[[UIDevice currentDevice] systemVersion]` where possible – Shai Nov 15 '13 at 13:11
  • Did you have any information for Xcode 6? – Nam Vu Aug 12 '15 at 07:29
  • I have just tried this with Xcode 7.3 and it doesn't seem to work. I will changing some project's build parameters. – Rivera May 10 '16 at 12:55

4 Answers4

1

I found some other information on the topic. This will redefine a different macro (NS_AVAILABLE_IOS). Perhaps it will work a bit better than

(Source https://www.albertopasca.it/whiletrue/xcode-warn-about-new-api-classes-and-methods/)

#import <availability.h>
#import <foundation/NSObjCRuntime.h>

#if( 1 )

#define APICHECK_2_0( _ios ) __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_##_ios)
#define APICHECK_2_1( _ios ) __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_##_ios)
#define APICHECK_2_2( _ios ) __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_##_ios)
#define APICHECK_3_0( _ios ) __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_##_ios)
#define APICHECK_3_1( _ios ) __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_##_ios)
#define APICHECK_3_2( _ios ) __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_##_ios)
#define APICHECK_4_0( _ios ) __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_##_ios)
#define APICHECK_4_1( _ios ) __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_##_ios)
#define APICHECK_4_2( _ios ) __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_##_ios)
#define APICHECK_4_3( _ios ) __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_##_ios)
#define APICHECK_5_0( _ios ) __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_##_ios)
#define APICHECK_5_1( _ios ) __attribute__((deprecated("UNAVAILABLE PRIOR TO 5.1")))
#define APICHECK_6_0( _ios ) __attribute__((deprecated("UNAVAILABLE PRIOR TO 6.0")))
#define APICHECK_6_1( _ios ) __attribute__((deprecated("UNAVAILABLE PRIOR TO 6.1")))
#define APICHECK_NA( _ios )  __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_##_ios)

#undef NS_AVAILABLE_IOS
#define NS_AVAILABLE_IOS(_ios) APICHECK_ ## _ios( _ios )

#undef NS_AVAILABLE
#define NS_AVAILABLE(_mac, _ios) APICHECK_ ## _ios( _ios )

#endif

You can use conditionals the same way as before (#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_6_0 etc). Note that I have not tested this because I don't have Xcode 5 on my machine yet. If you want to turn the warnings into errors you can use __attribute__((unavailable("UNAVAILABLE PRIOR TO 6.1"))) etc.

You can also try using this program, though it is paid. http://www.deploymateapp.com/

elp
  • 8,021
  • 7
  • 61
  • 120
borrrden
  • 33,256
  • 8
  • 74
  • 109
0

As of Xcode 5.0 it is not possible to get warnings from new API calls by redefining macros.

Redefining a macro does show up in autocompletion and preprocessed preview (Assistant Editor > Preprocess) but does not trigger a warning despite using deprecate or unavailable keywords.

Xcode 5.0.1+ does show a warning so both __AVAILABILITY_INTERNAL__IPHONE_X_X and NS_AVAILABLE_IOS can now be redefined as mentioned in the question and @borrrden answer.

Code available as a Gist and as a library:

#define __IPHONE_OS_VERSION_SOFT_MAX_REQUIRED __IPHONE_5_0

#ifndef __IPHONE_OS_VERSION_SOFT_MAX_REQUIRED
    #define __IPHONE_OS_VERSION_SOFT_MAX_REQUIRED __IPHONE_OS_VERSION_MIN_REQUIRED
#endif

#if __IPHONE_OS_VERSION_SOFT_MAX_REQUIRED < __IPHONE_OS_VERSION_MIN_REQUIRED
    #error You cannot ask for a soft max version which is less than the deployment target
#endif

#define __NBU_AVAILABILITY_STARTING(version) __attribute__((deprecated("Only available in iOS " version "+"))) __attribute__((weak_import))

#if __IPHONE_OS_VERSION_SOFT_MAX_REQUIRED < __IPHONE_2_0
    #undef  __AVAILABILITY_INTERNAL__IPHONE_2_0
    #define __AVAILABILITY_INTERNAL__IPHONE_2_0 __NBU_AVAILABILITY_STARTING("2.0")
    #define __NBU_APICHECK_2_0(_ios)            __NBU_AVAILABILITY_STARTING("2.0")
#else
    #define __NBU_APICHECK_2_0(_ios)            CF_AVAILABLE_IOS(_ios)
#endif

#if __IPHONE_OS_VERSION_SOFT_MAX_REQUIRED < __IPHONE_2_1
    #undef  __AVAILABILITY_INTERNAL__IPHONE_2_1
    #define __AVAILABILITY_INTERNAL__IPHONE_2_1 __NBU_AVAILABILITY_STARTING("2.1")
    #define __NBU_APICHECK_2_1(_ios)            __NBU_AVAILABILITY_STARTING("2.1")
#else
    #define __NBU_APICHECK_2_1(_ios)            CF_AVAILABLE_IOS(_ios)
#endif

//...

#if __IPHONE_OS_VERSION_SOFT_MAX_REQUIRED < __IPHONE_7_0
    #undef  __AVAILABILITY_INTERNAL__IPHONE_7_0
    #define __AVAILABILITY_INTERNAL__IPHONE_7_0 __NBU_AVAILABILITY_STARTING("7.0")
    #define __NBU_APICHECK_7_0(_ios)            __NBU_AVAILABILITY_STARTING("7.0")
#else
    #define __NBU_APICHECK_7_0(_ios)            CF_AVAILABLE_IOS(_ios)
#endif

#undef  NS_AVAILABLE_IOS
#define NS_AVAILABLE_IOS(_ios)                  __NBU_APICHECK_##_ios( _ios )

#undef  __OSX_AVAILABLE_BUT_DEPRECATED
#define __OSX_AVAILABLE_BUT_DEPRECATED(_osx, _osxDep, _ios, _iosDep)            __AVAILABILITY_INTERNAL##_ios

#undef  __OSX_AVAILABLE_BUT_DEPRECATED_MSG
#define __OSX_AVAILABLE_BUT_DEPRECATED_MSG(_osx, _osxDep, _ios, _iosDep, _msg)  __AVAILABILITY_INTERNAL##_ios
Rivera
  • 10,792
  • 3
  • 58
  • 102
0

In Xcode 5, you should be able to use/adapt the code from my answer to https://stackoverflow.com/a/19567669/473067. It could be incompatible with the use of modules, though, I haven't checked.

I posted a summary here: http://iphone.m20.nl/wp/2013/10/xcode-5-and-flagging-weak-linked-unavailable-symbols-from-a-newer-sdk/

Community
  • 1
  • 1
Steven Kramer
  • 8,473
  • 2
  • 37
  • 43
0

Use the method described here: https://stackoverflow.com/a/8919108/480467

In addition, to get this to work under XCode 5 you need to also redefine the NS_AVAILABLE and NS_DEPRECATED macros because CFAvailability.h distinguishes between compilers that support the attribute_availability_with_message feature.

See my response here: https://stackoverflow.com/a/19704587/480467

Community
  • 1
  • 1
Werner Altewischer
  • 10,080
  • 4
  • 53
  • 60
  • `NS_AVAILABLE` uses `CF_AVAILABLE` so it suffices to redefine the former. As for deprecations I just redefined `__OSX_AVAILABLE_BUT_DEPRECATED ` and `__OSX_AVAILABLE_BUT_DEPRECATED_MSG` because this code is only meant to be commented out most of the time and only serves to check the currently available (but too new) API calls. Thanks, I updated the answer as well. – Rivera Nov 01 '13 at 06:09