objective-c - 编译器如何确定哪些消息可以发送到 id 类型变量?

标签 objective-c ios compiler-construction

我在 Xcode 中使用 TabBarController 模板尝试一些操作时遇到了这个“问题”(这并不是真正的问题,我只是惊讶于这是可能的)。如果您使用没有 Storyboard的模板,则基本设置如下所示:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
UIViewController *viewController1 = [[FirstViewController alloc] initWithNibName:@"FirstViewController" bundle:nil];
UIViewController *viewController2 = [[SecondViewController alloc] initWithNibName:@"SecondViewController" bundle:nil];
self.tabBarController = [[UITabBarController alloc] init];

self.tabBarController.viewControllers = @[viewController1, viewController2];

self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}

tabBarController 的 viewControllers 属性是一个 NSArray。因此,[self.tabBarController objectAtIndex:0] 返回一个 id

所以我一直在想,如果我想调用我在 f.e. 声明的方法。 FirstViewController 类,我必须这样做:

FirstViewController *firstVC = (FirstViewController *)[self.tabBarController objectAtIndex:0];
[firstVC someMethod];

但事实证明,这是不必要的,编译器还会允许我执行以下操作 - 只要我导入声明 someMethod 的头文件(当然,它不一定会增加可读性,但无论如何):

[[self.tabBarController objectAtIndex:0] someMethod];

我根本没想到会这样。因此,我假设编译器将允许在 id 上调用任何方法,只要该方法是在当前类范围内的任何类中声明的(我的意思是,它的头文件被导入到当前类(class))。如果未导入声明 someMethod 的类,编译器将抛出错误(但我必须补充一点,我在使用 ARC 时对此进行了测试。编译器很可能不会提示关于在不使用 ARC 时调用 id 上的“未导入”方法)...

这个假设正确吗?如果可能的话,您能否提供一些有关 id 类型的更多信息或引用?

或者编译器是否允许在 ARC 之前调用 id 上的任何方法(导入或未导入),而现在对未导入方法的提示只是 ARC 的结果?

非常感谢。

最佳答案

Or did the compiler allow calling any method on id (imported or not) before ARC, and the complaint now for unimported methods is just a result of ARC?

这是正确的。如果没有 ARC,这就是一个警告。对于 ARC,这是一个错误(因为如果 ARC 在这里猜测错误,它可能会遇到严重的问题)。

在某些情况下,无论有或没有 ARC,此行为都可能导致一些非常微妙的错误。如果有多个方法签名与选择器匹配,则编译器可能会选择错误的返回类型,这可能会导致非常令人惊讶的运行时行为。 Matt Gallagher 在 "A big weakness in Objective-C's weak typing." 中对此提供了很好的解释。我遇到了他所描述的同样的错误,ObjC 开发人员应该意识到这一点,尽管它并不经常出现。

关于objective-c - 编译器如何确定哪些消息可以发送到 id 类型变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13077256/

相关文章:

ios - 从远程服务器在 init 方法中填充 tableview 数据源

ios - 找到一周中依赖于语言环境的第一天

ios - Ionic 4 Ios构建越来越黑屏

ios - 如何重置可重复使用细胞的外观?

C++方法返回指向抽象类的指针,需要使用子类中的方法

c++ - 如何为 Qt 而不是 MinGW 设置 Visual Studio 2012 RC 编译器?

c++ - 关于应用程序速度,最好的 C++ 编译器和 Windows 构建选项?

ios - 如何在不使用临时文件的情况下在 UIWebview 中打开受密码保护的 PDF/DOC?

iphone - "error launching remote program: device locked out"xcode 4.2.1 和 ipad 5.0.1

ios - 使用标题 View 自定义导航栏