| 如果在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中定义的方法 (编辑:宣城站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |