【问题标题】:Get Xcode 5 to warn about new API calls获取 Xcode 5 以警告新的 API 调用
【发布时间】:2013-10-07 08:41:11
【问题描述】:

有一个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

但这不再起作用了,因为 iOS 7 SDK 可用性宏已经改变,现在有更多的变化和选项:

iOS 6 SDK 的 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)))

会不会是 Xcode 5 有 attribute_availability_with_message 功能,所以旧的宏重定义不再使用?

此外,打印比“太新!”更多的内容会很酷。包含所有新引入/弃用信息的消息。

编辑:

iOS 7 SDK 中的大部分定义从 __OSX_AVAILABLE_STARTING(_ios)/__AVAILABILITY_INTERNAL##_ios 移至 NS_AVAILABLE_IOS(_ios)/CF_AVAILABLE_IOS(_ios),因此重新定义:

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

应该可以。实际上它确实如此,因为 Xcode 5 自动补全显示这些方法已弃用。

尽管打开了GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS 构建选项,但构建不会触发任何警告...

【问题讨论】:

  • __AVAILABILITY_INTERNAL__IPHONE_7_0 吗?
  • 那我的回答可能会奏效。试试看。
  • 有点用。请参阅编辑说明。
  • 对属性尝试“不可用”而不是“已弃用”。
  • 首先我知道为什么 Xcode 不会触发那些弃用警告 stackoverflow.com/questions/18197326/…。至于不可用,结果是一样的。

标签: ios objective-c api ios7 xcode5


【解决方案1】:

我发现了有关该主题的一些其他信息。这将重新定义一个不同的宏 (NS_AVAILABLE_IOS)。也许它会比

(来源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

您可以像以前一样使用条件句(#if __IPHONE_OS_VERSION_MIN_REQUIRED &lt; __IPHONE_6_0 等)。请注意,我没有对此进行测试,因为我的机器上还没有 Xcode 5。如果您想将警告变成错误,您可以使用__attribute__((unavailable("UNAVAILABLE PRIOR TO 6.1"))) 等。

您也可以尝试使用此程序,尽管它是付费的。 http://www.deploymateapp.com/

【讨论】:

  • 感谢这对我有帮助,但__AVAILABILITY_INTERNAL 仍然在某些地方。
【解决方案2】:

从 Xcode 5.0 开始,无法通过重新定义宏来从新的 API 调用中获得警告。

重新定义宏确实会显示在自动完成和预处理预览中(Assistant Editor > Preprocess),但尽管使用了deprecateunavailable 关键字,但不会触发警告。

Xcode 5.0.1+ 确实显示警告,因此__AVAILABILITY_INTERNAL__IPHONE_X_XNS_AVAILABLE_IOS 现在可以按照问题和@borrrden 答案中的说明重新定义。

代码以Gistlibrary 的形式提供:

#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

【讨论】:

    【解决方案3】:

    在 Xcode 5 中,您应该能够使用/调整我对 https://stackoverflow.com/a/19567669/473067 的回答中的代码。不过,它可能与模块的使用不兼容,我还没有检查过。

    我在这里发布了一个摘要:http://iphone.m20.nl/wp/2013/10/xcode-5-and-flagging-weak-linked-unavailable-symbols-from-a-newer-sdk/

    【讨论】:

      【解决方案4】:

      使用这里描述的方法:https://stackoverflow.com/a/8919108/480467

      此外,要使其在 XCode 5 下工作,您还需要重新定义 NS_AVAILABLE 和 NS_DEPRECATED 宏,因为 CFAvailability.h 区分了支持 attribute_availability_with_message 功能的编译器。

      在这里查看我的回复:https://stackoverflow.com/a/19704587/480467

      【讨论】:

      • NS_AVAILABLE 使用 CF_AVAILABLE 所以重新定义前者就足够了。至于弃用,我刚刚重新定义了__OSX_AVAILABLE_BUT_DEPRECATED __OSX_AVAILABLE_BUT_DEPRECATED_MSG,因为这段代码大部分时间只用于注释掉,仅用于检查当前可用的(但太新的)API 调用。谢谢,我也更新了答案。
      猜你喜欢
      • 1970-01-01
      • 2011-06-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-03
      • 2017-01-23
      • 2012-12-19
      相关资源
      最近更新 更多