如果在Swift中的使用了OC类,比如还在使用的UIViewController、UIView等等。并且还重写了基类的方法,比如一定会重写UIViewController的viewDidLoad方法。对于这些类的重写的方法定义信息还是会保存在类的Class结构体中,而在调用上还是采用OC语言的Runtime机制来实现,即通过objc_msgSend来调用。而如果在OC派生类中定义了一个新的方法的话则实现和调用机制就不会再采用OC的Runtime机制来完成了,比如说在UIView的派生类中定义了一个新方法foo,那么这个新方法的调用和实现将与OC的Runtime机制没有任何关系了! 它的处理和实现机制会变成我下面要说到的第三种方式。下面的Swift源代码以及C伪代码实现说明了这个情况:
- ////////Swift源代码
-
- //类定义
- class MyUIView:UIView {
- open func foo(){} //常规方法
- override func layoutSubviews() {} //重写OC方法
- }
-
- func main(){
- let obj = MyUIView()
- obj.layoutSubviews() //调用OC类重写的方法
- obj.foo() //调用常规的方法。
- }
-
- ////////C伪代码
-
- //...........................................运行时定义部分
-
- //OC类的方法结构体
- struct method_t {
- SEL name;
- IMP imp;
- };
-
- //Swift类描述
- struct swift_class {
- ... //其他的属性,因为这里不关心就不列出了。
- struct method_t methods[1];
- ... //其他的属性,因为这里不关心就不列出了。
- //虚函数表刚好在结构体的第0x50的偏移位置。
- IMP vtable[1];
- };
-
-
- //...........................................源代码中类的定义和方法的定义和实现部分
-
- //类定义
- struct MyUIView {
- struct swift_class *isa;
- }
-
- //类的方法函数的实现
- void layoutSubviews(id self, SEL _cmd){}
- void foo(){} //Swift类的常规方法中和源代码的参数保持一致。
-
- //类的描述信息构建,这些都是在编译代码时就明确了并且保存在数据段中。
- struct swift_class classMyUIView;
- classMyUIView.methods[0] = {"layoutSubviews", &layoutSubviews};
- classMyUIView.vtable[0] = {&foo};
-
-
- //...........................................源代码中程序运行的部分
-
- void main(){
- MyUIView *obj = MyUIView.__allocating_init(classMyUIView);
- obj->isa = &classMyUIView;
- //OC类重写的方法layoutSubviews调用还是用objc_msgSend来实现
- objc_msgSend(obj, @selector(layoutSubviews);
- //Swift方法调用时对象参数被放到x20寄存器中
- asm("mov x20, obj");
- //Swift的方法foo调用采用间接调用实现
- obj->isa->vtable[0]();
- }
extension中定义的方法 (编辑:晋中站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|