Object - C对象主要分为以下三种类型,具体如下:
1、实例对象(instance对象)
instance就是通过类alloc出来的对象,每次调用alloc都会产生新的instance对象(对象是否一样取决于其对应内存地址是否一样)
补充如下所示:
NSObject* objFirst = [[NSObject alloc] init];
NSObject* objSecond = [[NSObject alloc] init];
NSLog(@"objFirst对象地址:%p --- objSecond对象地址:%p", objFirst, objSecond);
运行如上代码,最终打印如下所示:
![](https://img.haomeiwen.com/i8379097/6fbe0c04e401f25f.png)
这样我们就可以说是objFirst 与 objSecond是两个不同的对象,因为占据2块不同的内存
实例对象的存储信息
- isa指针
- 其他成员变量
2、类对象(Class对象)
每个类的内存中有且只有一个类对象
补充如下(在上述代码基础上添加如下代码,这里传递的参数为instance对象,获取到的是instance对应的Class对象):
Class objFirstClass = [objFirst class];
Class objSecondClass = [objSecond class];
Class objFirst_runtime = object_getClass(objFirst);
Class objSecond_runtime = object_getClass(objSecond);
Class objClass = [NSObject class];//获取类对象
NSLog(@"objFirstClass对象地址:%p\nobjSecondClass对象地址:%p\nobjFirst_runtime对象地址:%p\nobjSecond_runtime对象地址:%p\nobjClass对象地址:%p", objFirstClass, objSecondClass, objFirst_runtime, objSecond_runtime, objClass);
-
object_getClass 这个是runtime的函数,使用时需要导入头文件 #import <objc/runtime.h>
运行如上代码,最终打印如下所示:
图片.png
可以看出,上面的Class 对象内存地址均相同,那就说明这都是同一个对象,这也验证了每个类在内存中有且只有一个Class对象
类对象的存储信息
- isa指针
- superClass指针
- 类的属性信息(@property),类的对象方法信息(即 - 开头的方法method),类的协议信息(protocol),类的成员变量信息(ivar)
- 类的成员变量信息(这里需要区分instance对象中所包含的成员变量信息)
- insatance对象中所包含的成员信息是指对应的值(具体的值)
- Class对象中所包含的成员信息是指对应的名称,类型等
简单代码如下:(具体表现为 25 是在instance对象中,int 类型 _age 这些信息是在Class对象中,所以说Class对象中也是包含类的成员信息):
- 类的成员变量信息(这里需要区分instance对象中所包含的成员变量信息)
@interface Person : NSObject{
@public
int _age;
}
@end
@implementation Person
-(void)setAge:(int) age{
_age = age;
}
Person* person = [[Person alloc] init];
person -> _age = 25;
3、元类对象(meta-class对象)
每个类的内存中有且只有一个元类对象
补充如下(在上述代码基础上添加如下代码,这里参数一定要是Class对象,这样获取到的才是meta-class对象):
Class objFirst_meta = object_getClass([objFirst class]);
Class objSecond_meta = object_getClass([objSecond class]);
Class objc_meta = object_getClass([NSObject class]);
NSLog(@"\nobjFirst_meta对象地址:%p\nobjSecond_meta对象地址:%p\nobjc_meta对象地址:%p", objFirst_meta, objSecond_meta, objc_meta);
运行如上代码,最终打印如下所示:
![](https://img.haomeiwen.com/i8379097/a2338f28c2762335.png)
同样的以上对象的地址均一致,也验证了每个类在内存中有且只有一个meta - class对象
元类的存储信息
-
isa指针
-
superClass指针
-
类方法信息(即 + 开头的方法 method)
-
类对象/元类对象其实都是Class对象,所以他们的内存结构其实是一样的,但是用途不一样,主要体现在存贮的信息不一样,例如元类对象存贮的就是类方法信息,而类对象存储的就是类对象方法信息等。。。
-
元类对象其实也可以看成是特殊的类对象
用一副图很形象的可以表现出来,如下所示
Object - C 类结构图.png
本文中的参考代码贴出如下所示,都相对比较简单:
NSLog(@"----------------instance - start--------------------------");
//instance对象
NSObject* objFirst = [[NSObject alloc] init];
NSObject* objSecond = [[NSObject alloc] init];
NSLog(@"objFirst对象地址:%p\nobjSecond对象地址:%p", objFirst, objSecond);
NSLog(@"----------------instance - end--------------------------");
NSLog(@"----------------Class - start--------------------------");
//Class对象
Class objFirstClass = [objFirst class];
Class objSecondClass = [objSecond class];
Class objFirst_runtime = object_getClass(objFirst);
Class objSecond_runtime = object_getClass(objSecond);
Class objClass = [NSObject class];//获取类对象
NSLog(@"\nobjFirstClass对象地址:%p\nobjSecondClass对象地址:%p\nobjFirst_runtime对象地址:%p\nobjSecond_runtime对象地址:%p\nobjClass对象地址:%p", objFirstClass, objSecondClass, objFirst_runtime, objSecond_runtime, objClass);
NSLog(@"----------------Class - end--------------------------");
NSLog(@"----------------meta-class - start--------------------------");
//这里的参数必须是类对象
//meta-class对象
Class objFirst_meta = object_getClass([objFirst class]);
Class objSecond_meta = object_getClass([objSecond class]);
Class objc_meta = object_getClass([NSObject class]);
NSLog(@"\nobjFirst_meta对象地址:%p\nobjSecond_meta对象地址:%p\nobjc_meta对象地址:%p", objFirst_meta, objSecond_meta, objc_meta);
NSLog(@"----------------meta-class - end--------------------------");
说到这里再补充点东西,object_getClass与objc_getClass,这两个看着很相似,有时候代码提示的时候敲得太快很容易混淆,这里可以具体看下:
- object_getClass
* Returns the class of an object.
*
* @param obj The object you want to inspect.
*
* @return The class object of which \e object is an instance,
* or \c Nil if \e object is \c nil.
*/
OBJC_EXPORT Class _Nullable
object_getClass(id _Nullable obj)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
上述是object_getClass的API,这里呢需要传递一个参数,参数是id类型,就是需要传递一个对象,返回一个class object,(注意:如果参数是instance对象,那么返回类对象,如果参数是类对象,那么返回对应的元类对象,这在上面已经验证过了)
- objc_getClass
/* Obtaining Class Definitions */
/**
* Returns the class definition of a specified class.
*
* @param name The name of the class to look up.
*
* @return The Class object for the named class, or \c nil
* if the class is not registered with the Objective-C runtime.
*
* @note \c objc_getClass is different from \c objc_lookUpClass in that if the class
* is not registered, \c objc_getClass calls the class handler callback and then checks
* a second time to see whether the class is registered. \c objc_lookUpClass does
* not call the class handler callback.
*
* @warning Earlier implementations of this function (prior to OS X v10.0)
* terminate the program if the class does not exist.
*/
OBJC_EXPORT Class _Nullable
objc_getClass(const char * _Nonnull name)
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
上述是objc_getClass的API,这里的参数是const char * 类型,这里它是需要传递一个类名的,返回一个类对象,那么这个到底是类对象还是元类对象呢,我们可以验证一下,如下代码:
Person* person = [[Person alloc] init];
NSLog(@"\n类对象_object_getClass:%p\n未知类型对象_objc_getClass:%p\n元类对象_object_getClass:%p", object_getClass(person), objc_getClass("Person"), object_getClass([Person class]));
最终的打印结果如下图所示:
![](https://img.haomeiwen.com/i8379097/a98dac7a6bf478b0.png)
这就很清楚了,未知类型对象的地址:0X1054b1368,与类对象完全一致,那就说明objc_getClass最终获取的其实是类对象
objc_getClass/object_getClass区别
- objc_getClass(const char * _Nonnull name)
a) 传入的是字符串类名objc_getClass("Person")
b) 返回对应的类对象 - object_getClass(id _Nullable obj)
a) 传入的obj可能是instance对象、class对象、meta-class对象
b) 返回结果
1.如果obj是instance对象,返回class对象(类对象)
2.如果obj是class对象,返回meta-class对象(元类对象)
3.如果obj是meta-class对象,返回基类的meta-class对象(元类对象)
+ (Class)class / - (Class)class (返回的就是类对象)
-
-(Class) class{
return self -> isa;
} -
+(Class) class{
return self;
}
如有疑问,欢迎私信,文中所述,希望可以帮助有需要的小伙伴,也算是简单做一个整理,方便日后回顾。。。
网友评论