如果使用了类别但没有添加到目标中,则没有警告(任何方式自动检查它?)

No warnings if category is used but isn't added into target(Any way check it automatically?)

我有一个类别 "NSObject+completeOnce"。我将它用于主要应用程序、手表、小部件。但我还没有将它添加到 watch 和 widget 目标中。我当然要去做。

我的问题是:"Why I don't see any warnings or linking errors in this case? Can I force them?"我的项目中有 100 多个 类,有时会做这样的 mitakes :(最好在运行之前找到一些方法来检查它。

类别声明:

//Category is added only into main target.
@interface NSObject (completeOnce)
+ (void)completeBlockOnce:(void(^)(void))block forKey:(NSString*)key
@end

用法:

@implementation SomeOtherClass
+ (void)method
{
    //It crashes for for widgets.
    //And Here is no any warnings. Also no linking errors at all
    [NSObject completeBlockOnce:^{
       //Some Code
    } forKey:@"FixMigrationBug_1_0_to_1_6"];
}
@end

我确定我只有一个此方法的声明。我必须强调,所有类别都是同一个问题。即使是我的自定义类别 类 具有 99% 的唯一方法名称。

您看到的是一个复合问题。您正在寻找两种类型的错误——编译器 warnings/errors 和链接器错误。你两者都没有,原因有二:

  1. 编译器实际上没有理由给你警告。为了让您进行方法调用,编译器只需要方法的 声明 (以便它正确排列参数,防止常见的用户错误等)。它实际上不需要知道该方法将以某种方式链接进来;那是链接器的工作。在这种情况下,由于您确实在 header 中声明了方法并包含 header,编译器会满意并且您不会收到警告,因为就编译器而言,该方法将稍后存在。
  2. 链接器不会为缺少的方法给出错误,因为 Objective-C does not produce linker symbols for methods(请参阅该页面上的 Objective-C header)。 Objective-C 本质上是一种非常动态的语言,因此在运行时之前不可能知道特定方法调用将做什么;事实上,可以在运行时定义静态不存在的方法。链接器只需要它拥有的 class 信息;方法的评估留给运行时。

这两件事共同导致了您所看到的行为。确保这些方法不存在的唯一方法是简单地尝试在运行时调用它们——现在,你会得到一个异常(如果未被捕获,会导致崩溃),因为它们实际上并没有被包含在内在应用程序二进制文件中。