iOS Runtime《一》 类Class 相关

Runtime简介

RunTime简称运行时。OC就是运行时机制,也就是在运行时候的一些机制,其中最主要的是消息机制。

对于C语言,函数的调用在编译的时候会决定调用哪个函数。

对于OC语言,属于动态调用过程,在编译的时候并不能决定真正调用哪个函数,只有在真正运行的时候才会根据函数的名称找到对应的函数来调用。事实证明:1、在编译阶段,OC可以调用任何函数,即使用这个函数并未实现,只要声明过就不会报错。2、在编码阶段,C语言调用未实现的函数就会报错。

一、获取类的名称

1、通过类获取类的名称

OBJC_EXPORT const char * _Nonnull
class_getName(Class _Nullable cls) 
    OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

参数:通过传入Class类型的cls来获的class的名字

例:

 //获取类名
    const char *className=class_getName([Dog class]);
    NSLog(@"%s",className);// Dog

2、通过对象获取类的名称

OBJC_EXPORT const char * _Nonnull object_getClassName(id _Nullable obj)
    OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);

例:

Dog *dog=[[Dog alloc]init];
    const char *className=object_getClassName(dog);
    NSLog(@"%s",className);//Dog

二、通过名称或对象获取类

1、
OBJC_EXPORT Class _Nullable
objc_getClass(const char * _Nonnull name)
    OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
2、
OBJC_EXPORT Class _Nullable
objc_lookUpClass(const char * _Nonnull name)
    OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
3、
OBJC_EXPORT Class _Nonnull
objc_getRequiredClass(const char * _Nonnull name)
    OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
4、
OBJC_EXPORT Class _Nullable
object_getClass(id _Nullable obj) 
    OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

以上为获取类的四种方法:

objc_getClass  objc_lookUpClass 返回当前类,当你找的类不存在,返回nil;

  objc_getRequiredClass 返回当前类,当你要找的类不存在的话会闪退,慎用。

 object_getClass 通过对象返回当前类

例:

Dog *dog=[[Dog alloc]init];
   
    // 1、通过c对象获取类
   Class objectGetClaas= object_getClass(dog);
    NSLog(@"%@",objectGetClaas);//Dog
    
    const char *className="Dog"; //当前类名存在
    const char *className1="Dog1";//当前类名不存在
    
    Class getClass=objc_getClass(className);
    NSLog(@"%@",getClass);//Dog
    Class getClass1=objc_getClass(className1);
    NSLog(@"%@",getClass1);//(null)
    
    Class lookUpClass=objc_lookUpClass(className);
    NSLog(@"%@",lookUpClass);//Dog
    Class lookUpClass1=objc_lookUpClass(className1);
    NSLog(@"%@",lookUpClass1);//(null)
    
    Class getRequiredClass=objc_getRequiredClass(className);
    NSLog(@"%@",getRequiredClass);//Dog
    Class getRequiredClass1=objc_getRequiredClass(className1);
    NSLog(@"%@",getRequiredClass1);//闪退 报错 link error: class 'Dog1' not found.

objc_getClass(const char * _Nonnull name) 与object_getClass(id _Nullable obj) 区别:

1、objc_getClass(const char * _Nonnull name)  传入字符串类名 返回对应的类对象

2、object_getClass(id _Nullable obj) 

a:传入obj可能是instance 对象返回的是 class对象

b:传入是class对象,返回meta-class对象

c:传入meta-class对象,返回NSObject(基类)的meta-class对象

三、元类对象

Class不仅可以代表类对象,还可以代表元类对象。 

1、获取元类对象

OBJC_EXPORT Class _Nullable
objc_getMetaClass(const char * _Nonnull name)
    OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);

例:

const char *className="Dog";
    Class metaClass=objc_getMetaClass(className);
    NSLog(@"%@",metaClass);//Dog

2、判断是否是元类对象

OBJC_EXPORT BOOL
class_isMetaClass(Class _Nullable cls) 
    OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

例:

const char *className="Dog";
    Class metaClass=objc_getMetaClass(className);
    Class class1=objc_getClass(className);
    BOOL isMetaClass1=class_isMetaClass(metaClass);
    BOOL isMetaClass2=class_isMetaClass(class1);
    NSLog(@"%d %d",isMetaClass1,isMetaClass2); //  1  0

3、判断 类(元类)对象和实例对象

objc_getClass 生成类类对象 ; class_isMetaClass 生成元类对象

OBJC_EXPORT BOOL
object_isClass(id _Nullable obj)
    OBJC_AVAILABLE(10.10, 8.0, 9.0, 1.0, 2.0);

只要是类对象或者元类对象都会返回YES

例:

const char *className="Dog";
    //类对象
    Class getClass=objc_getClass(className);
    
    //元类对象
    Class metaClass=objc_getMetaClass(className);
    
    //对象
     Dog *dog=[[Dog alloc]init];
    //只要是类对象或元类对象返回yes
    NSLog(@"%d",object_isClass(getClass)); //返回 1  是类对象
    NSLog(@"%d",object_isClass(metaClass)); //返回 1 是元类对象
    NSLog(@"%d",object_isClass(dog));  // 返回 0  实例对象

4、获取父类对象

OBJC_EXPORT Class _Nullable
class_getSuperclass(Class _Nullable cls) 
    OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

例:

const char *className="Dog";
    //类对象
    Class getClass=objc_getClass(className);
    Class getClassName=class_getSuperclass(object_getClass(getClass));
    NSLog(@"%@",getClassName); //NSObject

5、runtime里面的强转类型

OBJC_EXPORT Class _Nullable
object_setClass(id _Nullable obj, Class _Nonnull cls) 
    OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

例:

Dog *dog=[[Dog alloc]init];
    Class oldClass=object_setClass(dog, objc_getClass("NSObject"));
    NSLog(@"%@",oldClass);//Dog
    NSLog(@"%@",[dog class]);//NSObject

四、动态新增类

1、创建一个新类:
 参数 : superclass :是新类所继承的类,如果为nil. superclass为根类,NSObject
        name:是新类的名字。
        extraBytes:是在类和元类对象的末尾为索引ivars分配的字节数。这一般是0,
OBJC_EXPORT Class _Nullable
objc_allocateClassPair(Class _Nullable superclass, const char * _Nonnull name, 
                       size_t extraBytes) 
    OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

2、注册类:
如果一个类通过 objc_allocateClassPair 创建,必须注册之后才能使用:objc_registerClassPair
OBJC_EXPORT void
objc_registerClassPair(Class _Nonnull cls) 
    OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

3、此方法在系统KVO的底层用过,系统不推荐我们自己使用。
OBJC_EXPORT Class _Nonnull
objc_duplicateClass(Class _Nonnull original, const char * _Nonnull name,
                    size_t extraBytes)
    OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

4、销毁
bjc_disposeClassPair只能销毁通过objc_allocateClassPair创建的类。
OBJC_EXPORT void
objc_disposeClassPair(Class _Nonnull cls) 
    OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

例:

 const char * className="Cat";
    
    // 1、创建类
    Class cat=objc_allocateClassPair(objc_getClass("NSObject"), className, 0);
    NSLog(@"%@",objc_getClass(className));//(null)
    
    //2、注册类
    objc_registerClassPair(cat);
     NSLog(@"%@",objc_getClass(className));//Cat
    
    //3、销毁类
    objc_disposeClassPair(cat);
     NSLog(@"%@",objc_getClass(className));//(null)

五、获取注册类的方法

1、获取所有注册类的列表方式一:

OBJC_EXPORT Class _Nonnull * _Nullable
objc_copyClassList(unsigned int * _Nullable outCount)
    OBJC_AVAILABLE(10.7, 3.1, 9.0, 1.0, 2.0);

例:

unsigned int outCount;
    Class *classs=objc_copyClassList(&outCount);
    NSLog(@"总个数;%d",outCount);//总个数;15767
    for (int i=0; i<outCount; i++) {
        
        NSLog(@"%s",object_getClassName(classs[i]));
    }
    free(classs);

2、获取所有注册类的列表方式二:

OBJC_EXPORT int
objc_getClassList(Class _Nonnull * _Nullable buffer, int bufferCount)
    OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);

第一个参数buffer已分配好内存空间的数组指针,bufferCount是数组的个数,如果bufferCount的数量小于实际的数组数量,那么buffer返回的是所有数组集合的任意一个子类。如果buffer为NULL,那么bufferCount为0。无论那种情况,返回结果都是当前注册类的总数。

例:

 int bufferCount= 4;
    
    Class *buffer=(Class*)malloc(sizeof(Class)*bufferCount);
    
    int count1=objc_getClassList(buffer, bufferCount);
    
    for (int i=0; i<bufferCount; i++) {
        
        NSLog(@"name=%s",class_getName(buffer[i]));
        
    }
    NSLog(@"count1=%d",count1);
    
    int count2=objc_getClassList(NULL, 0);
    NSLog(@"count2=%d",count2);

六、类实例的大小

1、一个没有变量或属性的继承于NSObject的类占有8个字节

OBJC_EXPORT size_t
class_getInstanceSize(Class _Nullable cls) 
    OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

例:

size_t size =class_getInstanceSize(objc_getClass("Dog"));
    NSLog(@"%zu",size);

2、创建实例的方法

OBJC_EXPORT id _Nullable
class_createInstance(Class _Nullable cls, size_t extraBytes)
    OBJC_RETURNS_RETAINED
    OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);

cls是要创建的类,extraBytes是额外的字节内存,用来存储类定义中的实例变量之外的其他实例变量

例:

//OC创建对象
    Persion *p=[[Persion alloc]init];
    p.name=@"哈哈";
    NSLog(@"%@",p.name);//哈哈
    
    //runtime
    Persion *p1=class_createInstance(objc_getClass("Persion"), 0);
    p1.name=@"嘿嘿";
    NSLog(@"%@",p1.name);//嘿嘿

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值