美文网首页
iOS开发-底层源码探索的方式

iOS开发-底层源码探索的方式

作者: 在ios写bug的杰克 | 来源:发表于2020-12-01 14:44 被阅读0次

相关文章

iOS开发-底层原理总结 - 关联对象实现原理

iOS开发-底层原理 - KVO

[]

1.方法底层调用

首先写一个简单Demo

 #import <Foundation/Foundation.h>

    #import "XZPerson.h"
 
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
        // insert code here...
        XZPerson *p = [XZPerson alloc];
         
        [p sayHappy];
    }
    return 0;
}
 
 
#import <Foundation/Foundation.h>
 
NS_ASSUME_NONNULL_BEGIN
 
@interface XZPerson : NSObject
-(void)sayHappy;
 
@end
 
NS_ASSUME_NONNULL_END
 
#import "XZPerson.h"
 
@implementation XZPerson
-(void)sayHappy{
    NSLog(@"say happy")
}
@end

可以看出,很简单,只是在main函数中调用了一个XZPerson类中的一个方法,下面我们通过clang,对main文件进行编译;使用终端进入main文件目录:clang -rewrite-objc main.m -o main1.cpp ,同级目录下生成编译后cpp文件 直接查看main函数

int main(int argc, const char * argv[]) {
    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; 
 
        XZPerson *p = ((XZPerson *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("XZPerson"), sel_registerName("alloc"));
 
        ((void (*)(id, SEL))(void *)objc_msgSend)((id)p, sel_registerName("sayHappy"));
    }
    return 0;
}

我们将类型强转去掉方便我们对代码进行分析

int main(int argc, const char * argv[]) {
    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; 
 
        XZPerson *p = (objc_msgSend)(objc_getClass("XZPerson")
                                    ,sel_registerName("alloc"));
 
        (objc_msgSend)(p, sel_registerName("sayHappy"));
    }
    return 0;
}

这样我们就可以很清晰的看出来,方法的本质,其实就是底层通过objc_msgSend方法进行发送消息其中有2个参数

  • 参数一:消息接收者
  • 参数二:sel类型的方法编号
    这里的方法编号sel 就可以联系到上篇文章中的cache中,通过sel在找到imp 并在cache中进行方法查找,并进行返回

我们在main中写一个C语言的方法

#import <Foundation/Foundation.h>

#import "XZPerson.h"

void run(){

 NSLog(@"%s",__func__);

} 
int main(int argc, const char * argv[]) {
 @autoreleasepool {
 // insert code here...
        XZPerson *p = [XZPerson alloc];
        [p sayHappy];
        run();
    }
 return 0;
}

再次进行clang :这次输出main2.m文件,编译完成后查看源码

void run(){
    NSLog((NSString *)&__NSConstantStringImpl__var_folders_vl_y9rmzqq165ngxyd_yz2dmz0h0000gn_T_main_784d77_mi_0,__func__);
}
 
int main(int argc, const char * argv[]) {
    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; 
 
        XZPerson *p = ((XZPerson *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("XZPerson"), sel_registerName("alloc"));
 
        ((void (*)(id, SEL))(void *)objc_msgSend)((id)p, sel_registerName("sayHappy"));
 
        run();
    }
    return 0;
}

我们可以看到C语言方法,直接进行调用,而我们的OC方法需要使用objc_msgSend方法进行查找方法进行调用,这就说明

objc_msgSeng 方法其实就是OC方法进行查找底层实现的方法实现的过程并进行调用,而C语言函数实现可以直接找到C语言函数名就是函数指针直接找到地址进行调用;

原文链接:iOS底层探索八(方法本质上)

相关文章

网友评论

      本文标题:iOS开发-底层源码探索的方式

      本文链接:https://www.haomeiwen.com/subject/vrkswktx.html