runtime.h(一)

版本:iOS13.5

runtime.h

需要引入头文件#import
runtime其他方法通道

索引

  • 返回对象obj的复制。(ARC模式下不可用)
    object_copy
  • 释放对象obj占用的内存。(ARC模式下不可用)
    object_dispose
  • 返回对象obj的类。
    object_getClass
  • 为对象obj设置新类。
    object_setClass
  • 检测对象obj是否为Class的对象。
    object_isClass
  • 读取对象obj中实例变量的值。
    object_getIvar
  • 设置对象obj中实例变量的值。
    object_setIvar
  • 设置对象obj中实例变量的值。(strong)
    object_setIvarWithStrongDefault
  • 更改对象obj的实例变量的值。(ARC模式下不可用)
    object_setInstanceVariable
  • 更改对象obj的实例变量的值。(ARC模式下不可用)(strong)
    object_setInstanceVariableWithStrongDefault
  • 获取实例变量的值。(ARC模式下不可用)
    object_getInstanceVariable
  • 通过名称获取类对象。(没注册时调用处理回调)
    objc_getClass
  • 通过名称获取元类对象。
    objc_getMetaClass
  • 通过名称获取类对象。(没注册时不调用处理回调)
    objc_lookUpClass
  • 通过名称获取类对象。(没注册时会崩溃)
    objc_getRequiredClass
  • 获取已注册类的数量。(含系统类、cocoPods类)
    objc_getClassList
  • 获取已注册类的指针数组。(含系统类、cocoPods类)
    objc_copyClassList

详解

  • 返回对象obj的复制。(ARC模式下不可用)
id _Nullable object_copy(id _Nullable obj, size_t size)

obj objc对象
size 对象的大小

  • 释放对象obj占用的内存。(ARC模式下不可用)
id _Nullable object_dispose(id _Nullable obj)
  • 返回对象obj的类。
Class _Nullable object_getClass(id _Nullable obj) 

可以通过NSStringFromClass(class)class_getName获取类的类名字符串
例子见object_isClass

  • 为对象obj设置新类。
Class _Nullable object_setClass(id _Nullable obj, Class _Nonnull cls)

cls 要设置的新类
Class 返回原来的类
例子见object_isClass

  • 检测对象obj是否为Class的对象。
BOOL object_isClass(id _Nullable obj)
例:
    NSMutableArray *arr = [NSMutableArray array];
    Class class = object_getClass(arr);
    NSString *name = NSStringFromClass(class);
    BOOL isClass = object_isClass(class);
    BOOL isClass1 = object_isClass(name);
    NSLog(@"%@ %@ %@", name, @(isClass), @(isClass1));
    
    Class class1 = object_setClass(arr, [NSDictionary class]);
    class = object_getClass(arr);
    name = NSStringFromClass(class);
    NSString *name1 = NSStringFromClass(class1);
    NSLog(@"%@ %@", name, name1);
输出:object_setClass后arr变成了NSDictionary
__NSArrayM 1 0
NSDictionary __NSArrayM
  • 读取对象obj中实例变量的值。
id _Nullable object_getIvar(id _Nullable obj, Ivar _Nonnull ivar) 

如果实例变量的Ivar是已知的,则object_getIvarobject_getInstanceVariable更快。

obj 包含该实例变量的对象
ivar 实例变量的Ivar描述 可通过runtime的class_getInstanceVariable获取
例子见object_setIvarWithStrongDefault

  • 设置对象obj中实例变量的值。
void object_setIvar(id _Nullable obj, Ivar _Nonnull ivar, id _Nullable value) 

如果实例变量的Ivar是已知的,则object_setIvarobject_setInstanceVariable更快。
变量如果具有已知内存管理(如ARC strong和weak)的实例变量则使用该内存管理。若为未知内存管理的实例变量则被分配为unsafe_unretained。

obj 包含该实例变量的对象
ivar 实例变量的Ivar描述 可通过runtime的class_getInstanceVariable获取
value 实例变量的新值
例子见object_setIvarWithStrongDefault

  • 设置对象obj中实例变量的值。(strong)
void
object_setIvarWithStrongDefault(id _Nullable obj, Ivar _Nonnull ivar, id _Nullable value) 

如果实例变量的Ivar是已知的,则object_setIvarobject_setInstanceVariable更快。
变量如果具有已知内存管理(如ARC strong和weak)的实例变量则使用该内存管理。若为未知内存管理的实例变量则被分配为strong。(和object_setIvar的不同之处)

strong强引用 指向并拥有该对象,根据引用计数来管理内存,置为nil时计数减1,计数为0时释放内存。
weak弱引用 指向但并不拥有该对象,置为nil时只是让指针为空,对象并不会释放。
unsafe_unretain和weak类似,只是置为nil时不会将指针设置成nil,所以会有野指针的可能。
所以,在ARC下,object_setIvarobject_setIvarWithStrongDefault的作用几乎一样。

例:
    self.title0 = @"runtime123";
    Ivar ivar = class_getInstanceVariable(self.class, "_title0");
    id name2 = object_getIvar(self, ivar);
    NSLog(@"name2:%@", name2);
    object_setIvar(self, ivar, @"runtime1234");
    id name3 = object_getIvar(self, ivar);
    NSLog(@"name3:%@", name3);
    object_setIvarWithStrongDefault(self, ivar, @"runtime12345");
    id name4 = object_getIvar(self, ivar);
    NSLog(@"name4:%@", name4);
输出:
name2:runtime123
name3:runtime1234
name4:runtime12345
  • 更改对象obj的实例变量的值。(ARC模式下不可用)
Ivar _Nullable object_setInstanceVariable(id _Nullable obj, const char * _Nonnull name,
                           void * _Nullable value)

obj 包含该实例变量的对象。
name 实例变量的名称
value 实例变量的新值void *
Ivar 返回实例变量的Ivar描述

  • 更改对象obj的实例变量的值。(ARC模式下不可用)(strong)
Ivar _Nullable object_setInstanceVariableWithStrongDefault(id _Nullable obj,
                         const char * _Nonnull name, void * _Nullable value)

object_setInstanceVariableWithStrongDefaultobject_setInstanceVariable的不同之处与object_setIvarWithStrongDefaultobject_setIvar的不同之处一致。

  • 获取实例变量的值。(ARC模式下不可用)
Ivar _Nullable object_getInstanceVariable(id _Nullable obj, const char * _Nonnull name,
                           void * _Nullable * _Nullable outValue)

obj 包含该实例变量的对象。
name 实例变量的名称
outValue void **指针,保存实例变量的值。
Ivar 返回实例变量的Ivar描述

  • 通过名称获取类对象。(没注册时调用处理回调)
Class _Nullable objc_getClass(const char * _Nonnull name)

objc_getClassobjc_lookUpClass的不同之处在于,如果未注册该类,objc_getClass会调用类处理程序回调,然后再次检查该类是否已注册。而objc_lookUpClass则不调用类处理程序回调。

name 类的名称
例子见objc_getMetaClass

  • 通过名称获取元类对象。
Class _Nullable objc_getMetaClass(const char * _Nonnull name)

元类 类所属的类(见例子) 弄懂OC中的类与元类

如果未注册该类,则此函数将调用类处理程序回调,然后再次检查该类是否已注册。但是,每个类定义都必须具有有效的元类,因此无论是否有效,总能返回元类。

name 类的名称

例:
    {
        NSArray *array = @[];
        //获取array的类
        Class class = object_getClass(array);
        //获取array的元类
        Class metaClass = object_getClass(class);
    }

    Class class2 = objc_getClass("NSArray");
    BOOL isCalss2 = object_isClass(class2);
    NSLog(@"%@ %@", @(isCalss2), class2);
    Class class3 = objc_getMetaClass("NSArray");
    BOOL isCalss3 = object_isClass(class3);
    NSLog(@"%@ %@", @(isCalss3), class3);
输出:
1 NSArray
1 NSArray
  • 通过名称获取类对象。(没注册时不调用处理回调)
Class _Nullable objc_lookUpClass(const char * _Nonnull name)

objc_getClassobjc_lookUpClass的不同之处在于,如果未注册该类,objc_getClass会调用类处理程序回调,然后再次检查该类是否已注册。而objc_lookUpClass则不调用类处理程序回调。

name 类的名称
例子见objc_getRequiredClass

  • 通过名称获取类对象。(没注册时会崩溃)
Class _Nonnull objc_getRequiredClass(const char * _Nonnull name)

objc_getRequiredClassobjc_getClass相同,但是如果找不到该类,则会崩溃。

例:
    Class class4 = objc_getMetaClass("NSArray");
    BOOL isCalss4 = object_isClass(class4);
    NSLog(@"%@ %@", @(isCalss4), class4);
    Class class5 = objc_getRequiredClass("NSArray1");
    BOOL isCalss5 = object_isClass(class5);
    NSLog(@"%@ %@", @(isCalss5), class5);
输出:会在objc_getRequiredClass处崩溃
1 NSArray
objc[34190]: link error: class 'NSArray1' not found.
  • 获取已注册类的数量。(含系统类、cocoPods类)
int objc_getClassList(Class _Nonnull * _Nullable buffer, int bufferCount)

Objective-C运行时库会自动注册源代码中所有类。您可以在运行时使用objc_addClass进行注册。

buffer 类的指针数组。可以传递NULL来获取已注册类的总数,而不用实际检索任何类。
bufferCount 要获取类的数量 bufferCount与已注册类总数以较小者为准 传0时为表示获取已注册类总数的类值 小于0时表示不取任何值
int 返回已注册类的总数

例:
    //获取已注册类的数量
    int classCount = objc_getClassList(NULL, 0);
    NSLog(@"total = %d", classCount);
    //为类的指针数组分配内存
    Class *classes = (__unsafe_unretained Class *)malloc(sizeof(Class) * classCount);
    ///获取前10个类
    objc_getClassList(classes, 10);
    NSMutableArray *resultArray = [NSMutableArray array];
    //创建信号 为1时可以保证数据线程安全
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
    dispatch_apply(10, dispatch_get_global_queue(0, 0), ^(size_t index) {
        //加锁
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        Class class = classes[index];
        [resultArray addObject:NSStringFromClass(class)];
        //解锁
        dispatch_semaphore_signal(semaphore);
    });
    NSLog(@"%@", resultArray);
    ///释放内存
    free(classes);
输出:
total = 20577
(
    JSExport,
    NSLeafProxy,
    NSProxy,
    "_UIActivityPlaceholderItemProxy",
    "_UITargetedProxy",
    "_UIViewServiceUIBehaviorProxy",
    "_UIViewServiceReplyControlTrampoline",
    "_UIViewServiceReplyAwaitingTrampoline",
    "_UIViewServiceImplicitAnimationDecodingProxy",
    "_UIViewServiceImplicitAnimationEncodingProxy"
)
  • 获取已注册类的指针数组。(含系统类、cocoPods类)
Class _Nonnull * _Nullable objc_copyClassList(unsigned int * _Nullable outCount)

必须使用free将返回值Class *释放

outCount 指针 保存已注册类的总数

例:
        unsigned int classCount;
        Class *classes = objc_copyClassList(&classCount);
        NSLog(@"total = %d", classCount);
        NSMutableArray *resultArray = [NSMutableArray array];
        dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
        dispatch_apply(10, dispatch_get_global_queue(0, 0), ^(size_t index) {
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            Class class = classes[index];
            [resultArray addObject:NSStringFromClass(class)];
            dispatch_semaphore_signal(semaphore);
        });
        NSLog(@"%@", resultArray);
        free(classes);
输出:
total = 20577
(
    JSExport,
    NSLeafProxy,
    NSProxy,
    "_UIActivityPlaceholderItemProxy",
    "_UITargetedProxy",
    "_UIViewServiceUIBehaviorProxy",
    "_UIViewServiceReplyControlTrampoline",
    "_UIViewServiceReplyAwaitingTrampoline",
    "_UIViewServiceImplicitAnimationDecodingProxy",
    "_UIViewServiceImplicitAnimationEncodingProxy"
)

你可能感兴趣的:(runtime.h(一))