Pra*_*ari 0 cocoa dynamic objective-c objective-c-runtime
我是客观C的新手,从C/C++背景来看,我正在努力去理解客观C的动态.
请考虑以下代码:
id someObject = @"Hello, World!";
[someObject removeAllObjects];
Run Code Online (Sandbox Code Playgroud)
在这种情况下,someObject将指向一个NSString实例,但除了它是某种对象之外,编译器对该实例一无所知.所述removeAllObjects消息是由一些可可或可可触摸对象(如定义的NSMutableArray),从而,编译器不抱怨,即使该代码将在运行时生成异常,因为一个NSString对象无法removeAllObjects响应.
removeAllObjects消息由一些Cocoa或Cocoa Touch对象(例如NSMutableArray)定义,因此编译器不会抱怨.
这是否意味着,运行时实际上会查找所有实现的方法?如果是,它是否会影响性能?
请提出我的理解是否错误.
谢谢.
TheEye的答案是完全错误的,我认为对于那些刚接触Objective-C的人来说,了解它的实际工作方式非常重要.
Objective-C 中没有方法.您将消息发送到对象.这不仅仅是一个小的语法差异,它是一个根本不同的哲学.
当您将removeAllObjects消息发送到对象(无论是否声明为id或NSString*)时,实际发生的情况是,运行时在运行时查看对象的isa(is-a)指针,该指针指向该对象的定义.
每个对象定义都有一个对象实现的消息选择器列表.对于运行时性能,系统会缓存选择器.因此它将检查缓存是否已包含该选择器.如果是,则运行时跳转到该位置并开始执行在那里找到的代码.它还将检查继承类的链,以查看它们中是否有任何实现消息.
如果找不到该消息,它将发送选择器forwardInvocation:.出现这种情况的所有来历不明的邮件.碰巧NSObject的默认forwardInvocation:调用实现doesNotRecognizeSelector:会崩溃.
您可以通过forwardInvocation:在自己的课程上实施并无所事事来自行测试.然后尝试将随机选择器发送到您的类的实例.您将看到没有引发错误.这允许您创建检查,过滤或修改发往另一个对象的消息的代理对象.您还可以完全模拟其他课程.
代码中声明的变量类型只是一个提示,因此编译器可以帮助您在编译时捕获错误.在运行时,它并不重要.Objective-C只查看isa指针以确定对象的类,从而确定它支持的消息选择器.
这也是你可以在运行时覆盖类,向类中添加新方法等的原因.你甚至可以通过更改isa指针在运行时更改对象的类型,这将导致该对象的字节被重新解释为新型(警告:这是高级的东西所以请小心!)