instanceRespondToSelector 在不应该返回 true 时返回

Posted

技术标签:

【中文标题】instanceRespondToSelector 在不应该返回 true 时返回【英文标题】:instancesRespondToSelector returning true when it shouldn't 【发布时间】:2013-11-05 20:50:05 【问题描述】:

我正在编写一个向后兼容到 ios 6.0 的 iOS 应用程序。

在 iOS 7 中,NSString 实例方法 drawInRect:withAttributes: 替换了 drawInRect:withFont:lineBreakMode:alignment:。为了确定使用哪种方法,我有以下代码:

if ([NSString instancesRespondToSelector:@selector(drawInRect:withAttributes:)]) 
        NSMutableParagraphStyle *textStyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy];
        [textStyle setLineBreakMode:NSLineBreakByTruncatingTail];
        [textStyle setAlignment:NSTextAlignmentLeft];
        [[self title] drawInRect:_textRect withAttributes:@NSFontAttributeName: [UIFont boldSystemFontOfSize:FONT_SIZE], NSParagraphStyleAttributeName: textStyle];

else 
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
        [[self title] drawInRect:_textRect withFont:[UIFont boldSystemFontOfSize:FONT_SIZE] lineBreakMode:NSLineBreakByTruncatingTail alignment:NSTextAlignmentLeft];
#pragma clang diagnostic pop

由于drawInRect:withAttributes: 是在 iOS 7 中引入的,instancesRespondToSelector: 在早期版本的 iOS 上运行时应该返回 false。但是,在运行 iOS 6.1 的设备上测试它时,它返回 true,然后在尝试调用 drawInRect:withAttributes: 时崩溃。有谁知道发生了什么,或者我做错了什么?

【问题讨论】:

如果您测试 [[self title] respondsToSelector:@selector(drawInRect:withAttributes:)] 而不是使用方法“instancesRespondToSelector”,它将起作用。它在类别和类集群方面存在问题。 嗯,似乎没有修复它。仍然返回 true。 【参考方案1】:

仅仅因为某个方法不是给定版本的公共 API 的一部分,并不意味着它不存在。我的猜测是-drawInRect:withAttributes: 在 iOS 6 中是私有 API,然后在 iOS 7 中被提升为公共 API。您可以在此处测试您知道仅在 iOS 6 上适用的其他条件。例如if (NSClassFromString(@"SomeiOS7OnlyClass") != Nil).

【讨论】:

所以 NSStringDrawing.h 中的 MACRO NS_AVAILABLE_IOS(7_0) 应该做什么?? 猜猜这只是苹果的怪癖。将这个答案标记为正确只是因为它有效,但真正的答案仍然是个谜。 @elio.d,NS_AVAILABLE_IOS 宏只是对编译器的提示,允许根据 API 使用情况发出(编译时)警告等。当您将标题作为文档阅读时,它也很有用.它与运行时行为无关。 @Kamaros,老实说,我懒得安装一个包括 iOS 6.0 SDK 的开发环境来检查这个,只是为了回答你的问题,但它很容易测试。使用 iOS 6 SDK 构建应用程序,并在运行时执行相同的测试。如果返回YES,我说的是正确的。 @iVishal,是的,_-前缀方法是私有的。然而,仅仅因为一个方法not_ 为前缀并不意味着它是公开的。公共方法在(公共)框架标头中公开并记录在案。 Apple 经常在一个版本中添加新的私有方法,然后在它们准备好在以后的版本中公开使用时将它们“提升”为公开。

以上是关于instanceRespondToSelector 在不应该返回 true 时返回的主要内容,如果未能解决你的问题,请参考以下文章