Runtime - ② - NSObject类
首先,我们都知道NSObject是大多数类的根类,但是,这个类的是怎么实现的呢?我们可以去下载开源的Runtime源码,探究下NSObject类的实现。
1. NSObject.h文件
我们可以直接使用Command点NSOject进去看到它的头文件,可以看到,NSObject.h文件中有两块内容:
- NSObject 协议
- NSObject 实现
1.1 NSObject 协议
@protocol NSObject
- (BOOL)isEqual:(id)object;
@property (readonly) NSUInteger hash;
@property (readonly) Class superclass;
- (Class)class OBJC_SWIFT_UNAVAILABLE("use 'type(of: anObject)' instead");
- (instancetype)self;
- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
- (BOOL)isKindOfClass:(Class)aClass;
- (BOOL)isMemberOfClass:(Class)aClass;
- (BOOL)conformsToProtocol:(Protocol *)aProtocol;
@end
这里只是粘贴了部分方法,其中也有很多我们熟悉的方法,比如判断代理是否实现某个方法,实现某个协议等等,这个也就解释了,为什么我们自定义的协议也要遵循NSObject的协议,我们可以直接使用NSObject协议中的方法,去判断代理是否实现了,因为协议有Optional这个关键字,协议的方法是可选实现的。
1.2 NSObject的成员变量
我们还是在NSObject.h文件中,可以看到,NSObject只有一个成员变量是Class类型的isa变量:
@interface Object
{
Class isa; /* A pointer to the instance's class structure */
}
那么Class类型是什么类型呢?我们可以大概的猜想一下,可能就是指它所属的类吧。
Now,我们Command继续看这个Class的实现。
1.3 Class是什么玩意?
typedef struct objc_class *Class;
简单明了,Class就是一个指向结构体的指针。关于这一块,不明白结构体指针的,还需要去补充一下这方面的知识。然后,我们继续看 objc_class 这个结构体:
struct objc_class {
Class _Nonnull isa OBJC_ISA_AVAILABILITY; // 还是那个指针 #if !__OBJC2__
Class _Nullable super_class // 父类 OBJC2_UNAVAILABLE;
const char * _Nonnull name // 类名 OBJC2_UNAVAILABLE;
long version // 版本 OBJC2_UNAVAILABLE;
long info // 包含信息 OBJC2_UNAVAILABLE;
long instance_size // 成员变量的size? OBJC2_UNAVAILABLE;
struct objc_ivar_list * _Nullable ivars // 成员变量存储list OBJC2_UNAVAILABLE;
struct objc_method_list * _Nullable * _Nullable methodLists // 类中的方法 OBJC2_UNAVAILABLE;
struct objc_cache * _Nonnull cache // 类中的方法缓存 OBJC2_UNAVAILABLE;
struct objc_protocol_list * _Nullable protocols // 类中的协议列表 OBJC2_UNAVAILABLE;
#endif
} OBJC2_UNAVAILABLE;
我们这里先看下isa指针:
- isa:在这个结构体中我们看到也有一个isa指针,这个isa指针指向的是meta class,这里补充一下,类其实也是一个对象就是类对象。
搞到这里有点晕了,我们可以看下id类型是个啥类型,可以对比一下。
1.4 id类型
struct objc_object {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
}; /// A pointer to an instance of a class.
typedef struct objc_object *id;
我们可以发现,id类型其实也是一个结构体指针啊,这里我们可以看到,objc_object 这个结构体中也有一个 isa变量。So,我们在NSObject,objc_class,objc_object中看到都有一个objc_class *类型,也就是Class类型的变量isa,可见这个isa是多么的重要啊。
我们可以得到大概这样的结论,在objc的runtime中,类是用objc_class结构体表示的,对象是用objc_object结构体表示的,对象的isa用来标示这个对象是哪一个类的实例。我们可以通过几个方法来验证一下。
2. NSObject.m
我们经常使用的判断一个对象是不是某个类或这个类的派生类的实例,那么我们就去看一下这两个方法的实现
- (Class)class {
return object_getClass(self);
} Class object_getClass(id obj){
if (obj) return obj->getIsa();
else return Nil;
} - (BOOL)isMemberOfClass:(Class)cls {
return [self class] == cls;
}
上面的三个方法简单明了,我们在判断一个对象是否是某个类的实例时,其实就是看这个对象中的isa指针是否指向某个类,当我们调用self class方法时,其实也就是拿到这个实例对象的isa指针,也就是指向结构体objc_class的指针,然后进行判断返回结果。所以,我们可以知道,对于某个普通的对象实例,通过调用[object class]其实返回的就是这个实例的isa变量。
一个类的实例对象的isa指针指向的是这个对象所属的类,这个类描述了一系列它的实例的特点,就像上面的objc_class结构体中的成员变量列表,成员函数的列表等。这个对象能够接受的消息列表也是存储在这个类中。
下面我们也分析一下objc_class,为什么也有一个isa变量呢?
在面向对象的世界中,万物皆对象,所以,类也是一个对象:类对象。它也有一个isa指针,那么它指向谁呢?我们可以看下 +Class方法的实现:
+ (Class)class {
return self;
}
为什么返回的竟然是self呢?我们知道对于某个类的实例来说,self总是指向其自身的,但是这里并没有实例啊,我们是直接调用了这个类的类方法啊,难道类本身也有一个self指针?这个方法的返回值是一个类对象,所以其本质还是一个对象。对于NSObject这样的类来说,它其实也就代表一个类对象,类对象的self指针应该指向的也是这个类对象自身。
Runtime - ② - NSObject类的更多相关文章
- 福利->KVC+Runtime获取类/对象的属性/成员变量/方法/协议并实现字典转模型
我们知道,KVC+Runtime可以做非常多的事情.有了这个,我们可以实现很多的效果. 这里来个福利,利用KVC+Runtime获取类/对象的所有成员变量.属性.方法及协议: 并利用它来实现字典转模型 ...
- Runtime获取类的属性列表和方法列表
Runtime获取类的属性列表和方法列表 Runtime很强大,他使得OC中没有真正意义上的私有属性和私有方法,我们可以利用OC的运行时拿到一个类的任何方法和任何属性,然后动态的去调用方法,objc_ ...
- NSObject类的API介绍
这篇文章围绕的对象就是NSObject.h文件,对声明文件中的属性.方法进行必要的“翻译”. 该文件大致由两部分组成:NSObject协议和NSObject类. (一)NSObject协议 - (BO ...
- 利用NSUserdefaults来存储自定义的NSObject类及自定义类数组
利用NSUserdefaults来存储自定义的NSObject类及自定义类数组 1.利用NSUserdefaults来存储自定义的NSObject类 利用NSUserdefaults也可以来存储及获取 ...
- 使用runtime给类动态添加方法并调用 - class_addMethod
上手开发 iOS 一段时间后,我发现并不能只着眼于完成需求,利用闲暇之余多研究其他的开发技巧,才能在有限时间内提升自己水平.当然,“其他开发技巧”这个命题对于任何一个开发领域都感觉不找边际,而对于我来 ...
- RunTime 给类添加属性
RunTime网上有很多人都不知道Runtime到底是干嘛的?有很多博主都是长篇大论给他们讲这个讲那个,我感觉还不如实例来的实在.很简单的一个例子:我们都知道会有这样的需求,未读消息列表的图片上要有一 ...
- Runtime单例模式类 -- 控制电脑关机
package demo1; import java.io.IOException; public class RunTimeDemo { public static void main(String ...
- IOS SEL (@selector) 原理及使用总结(二)
SEL消息机制工作原理是什么 引用下面文章: 我们在之前有提到,一个类就像一个 C 结构.NSObject 声明了一个成员变量: isa. 由于 NSObject 是所有类的根类,所以所有的对象都会有 ...
- Objective-C Runtime 运行时之一:类与对象
Objective-C语言是一门动态语言,它将很多静态语言在编译和链接时期做的事放到了运行时来处理.这种动态语言的优势在于:我们写代码时更具灵活性,如我们可以把消息转发给我们想要的对象,或者随意交换一 ...
随机推荐
- 鼠标事件-拖拽2(不能拖出指定对象的div)
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...
- Google APAC----Africa 2010, Qualification Round(Problem B. Reverse Words)----Perl 解法
原题地址链接:https://code.google.com/codejam/contest/351101/dashboard#s=p1 问题描述: Problem Given a list of s ...
- 如何使用火狐浏览器的Poster插件进行post请求
原文:http://blog.csdn.net/cjm2484836553/article/details/72453907 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] ...
- 前端构建工具Gulp的学习和使用
前几天刚鼓捣了Grunt的使用,结果文档还没捂热,老大说我们还是用gulp吧,搞得我又得来整gulp,眼泪流成河了,真是不晓得底层人民的辛苦啊.不过经过对gulp的学习,发现很好用,比grunt舒服! ...
- window 7 & 2008R2 多核cpu套接字泄露补丁
http://hotfixv4.microsoft.com/Windows%207/Windows%20Server2008%20R2%20SP1/sp2/Fix373886/7600/free/43 ...
- ActiveMQ5.8.0安装及启动
一.下载 官网地址:http://activemq.apache.org/download.html Windows版本:apache-activemq-5.8.0-bin.zip Linux版本:a ...
- Java实例---简单的投票系统
代码分析 InputData.java package vote; import java.io.BufferedReader; import java.io.IOException; import ...
- 推送代码到GitHub上的两种方式
要想将本地Git上代码提交到GitHub可以使用两种协议进行提交,分别使用HTTPS和SSH两种协议,如下所示. 当使用HTTPS协议时,每次推送的时候都需要输入GitHub平台的用户名密码. ...
- SQL server reporting service - rsReportServerNotActivated error solution
描述: 今天在原有的数据库版本上增加了Reporting Service 功能,数据库完成安装后,没有发现ReportServer和 ReportServerTemp 两个数据库 于是从其他服务器上, ...
- 云端办公是 Office系统的未来方向么 ?
云端办公是 Office系统的未来方向么 ? 话说随着互联网,HTML技术,云计算等技术的发展,越来越多的应用已经迁移到云端, 以我们熟悉的电脑游戏为例,从单机游戏,到网络游戏,再到网页游戏,基本就是 ...