美文网首页
iOS RunTime常用内容总结

iOS RunTime常用内容总结

作者: _菩提本无树_ | 来源:发表于2023-01-16 16:54 被阅读0次
- (void)runtime {
    /// 获取类名
    const char *className = class_getName([NSObject class]);
    
    /// 获取父类
    Class supperClass = class_getSuperclass([self class]);
    
    /// 判断某个类是否是metaclass
    BOOL isMeta =class_isMetaClass([NSObject class]);
    
    /// 获取生成对象需要的大小
    size_t size = class_getInstanceSize([self class]);
    
    /// 获取实例变量(在类中声明变量的时候会自动生成实例变量,加下划线即可获取)
    Ivar ivar = class_getInstanceVariable([self class], "_allDataArr");
    
    /// 这个方法表示的是类变量,但是公开的api是没有这个的,或许是内部使用的方法,目前用不到
    Ivar ivarClass = class_getClassVariable([self class], "");
    
    /// 该函数只能在动态添加类中使用有效,且只能在objc_allocatelasspair()之后和objc_registerClassPair()之前调用,
    /// 动态生成类
    Class Person = objc_allocateClassPair([NSObject class], "Person", 0);
    BOOL addOvar = class_addIvar([Person class], "_myData", sizeof(NSString *), log2(sizeof(NSString *)), "@");
    BOOL addOvar1 = class_addIvar([Person class], "_myData1", sizeof(NSString *), log2(sizeof(NSString *)), "@");
    objc_registerClassPair(Person);
    /// 给成员变量赋值
    id person = Person.new;
    Ivar personIvar = class_getInstanceVariable([Person class], "_myData");
    object_setIvar(person, personIvar, @"test");
    NSLog(@"ivar值:%@",object_getIvar(person, personIvar));
    
    /// 获取实例变量列表
    unsigned int ivarCount;
    Ivar *ivars = class_copyIvarList([self class], &ivarCount);
    
    /// 获取类中使用strong修饰的实例对象列表
    /// 这个方法获取的内容值的解读,参考 https://www.51cto.com/article/493255.html
    const uint8_t *strongs = class_getIvarLayout([self class]);
    int i = 0;
    uint8_t value_s = strongs[i];
    while (value_s != 0x0) {
        printf("\\x%02x\n", value_s);
        value_s = strongs[++i];
    }
    
    /// 获取类中使用weak修饰的实例对象列表(strong和weak都未获得的是基本数据类型)
    const uint8_t *weaks = class_getWeakIvarLayout([DDCollectionCycleController class]);
    
    /// 添加实例对象修饰符(strong,weak,retain......)该方法未理清
    //    class_setIvarLayout([Person class], <#const uint8_t * _Nullable layout#>)

    /// 获取属性
    objc_property_t property_t = class_getProperty([self class], "property");
    
    /// 获取属性列表
    unsigned int property_count;
    objc_property_t *property_list = class_copyPropertyList([self class], &property_count);
    
    /// 动态添加方法
    SEL sel = NSSelectorFromString(@"testMethod");
    Method method_t = class_getInstanceMethod([self class], sel);
    BOOL isMethod = class_addMethod([self class], sel, method_getImplementation(method_t), method_getTypeEncoding(method_t));
    
    /// 获取指定对象方法
    Method methodInstance = class_getInstanceMethod([self class], @selector(testMethod));
    
    ///获取类方法
    Method methodClass = class_getClassMethod([self class], @selector(classMethod));
    
    /// 获取方法列表
    unsigned int methodCount;
    Method methodInstance_list = class_copyMethodList([self class], &methodCount);
    
    /// 方法替换
    class_replaceMethod([self class], @selector(swizzMethod), class_getMethodImplementation([self class], @selector(originMethod)), method_getTypeEncoding(class_getInstanceMethod([self class], @selector(originMethod))));
    
    /// 获取方法的imp
    IMP imp = class_getMethodImplementation([self class], @selector(originMethod));
    
    /// 查找类中是否包含某个实例方法,但是官方不建议使用这个方法建议使用 respondsToSelector: 或者 instancesRespondToSelector:
    BOOL isContainMethod = class_respondsToSelector([self class], @selector(originMethod));
    
    /// 添加协议Protocol到类中
    Protocol *protocol = @protocol(UITextFieldDelegate);
    BOOL isProtocol = class_addProtocol([self class], protocol);
    
    /// 添加属性
    Class currentClass = [self class];
    NSString * propertyName = @"myProperty";
    // type(举例NSString类型)
    objc_property_attribute_t type = { "T", "@\"NSString\""};
    // C = copy
    objc_property_attribute_t ownership0 = { "C", "" };
    // N = nonatomic
    objc_property_attribute_t ownership = { "N", "" };
    // instance variable name
    objc_property_attribute_t backingivar  = { "V", [[NSString stringWithFormat:@"_%@", propertyName] UTF8String] };
    // 对比系统生成的顺序,例如我们静态添加的grade属性
    objc_property_attribute_t attrs[] = { type, ownership0, ownership, backingivar};
    BOOL isProperty = class_addProperty(self.class, "myProperty", attrs, 4);
    if (!isProperty) {
        // 添加属性失败,替换属性
        class_replaceProperty(currentClass, "myProperty", attrs, 4);
    }
    // 添加get和set方法不好使,一直闪退,所以通过关联对象的方式添加
    // BOOL add = class_addMethod(currentClass, NSSelectorFromString(propertyName), (IMP)getter, "@@:");
    // BOOL addM = class_addMethod(currentClass, NSSelectorFromString(@"setMyProperty:"), (IMP)setter, "v@:@");
    objc_setAssociatedObject(self, "myProperty", @"12233", OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    NSString *valueData = objc_getAssociatedObject(self, "myProperty");
    
    /// 检测某个类是否遵循某个协议,官方不建议使用这个方法,使用NSObject的conformsToProtocol:
    BOOL isConformsProtocol = class_conformsToProtocol([self class], @protocol(UITableViewDelegate));
    
    /// 设置类的版本号,不明白这个用来干啥的
    class_setVersion(self.class, 2);
    /// 获取类的版本号
    int n = class_getVersion(self.class);
    
    ///objc_getFutureClass , objc_setFutureClass这两个方法官方原话是Do not call this function yourself
    
    /// 动态添加类
    Class PlusClass = objc_allocateClassPair([NSObject class], "PlusClass", 0);
    objc_registerClassPair(PlusClass);
    /// 创建对象
    id plus = class_createInstance(PlusClass.class, sizeof(unsigned));
    id strInstance = class_createInstance(NSString.class, sizeof(unsigned));
    strInstance = @"string";
    /// 释放类     !!!不要调用这个方法,如果有子类继承或者对象使用这个类
    /// objc_disposeClassPair(PlusClass);
    /// objc_destructInstance,objc_constructInstance arc下无法使用
    
    /// 获取实例关联的信息,一个list
    void * indexedIvars = object_getIndexedIvars(plus);
    
    /// 给实例变量赋值
    object_setIvar(person, personIvar, @"上面已经赋值了,我是第二次赋值");
    
    /// 获取实例变量Ivar存储的值,前提是保证Ivar存在
    id ivar_item = object_getIvar(person, personIvar);
    
    /// 根据对象获取类名
    char *name = object_getClassName(person);
    
    /// 获取类对象
    Class class = object_getClass(person);
    
    /// 讲一个对象设置其他类类型,返回之前的class
    Class replaceClass = object_setClass(plus, NSString.class);
    plus = @"11111";
    
    /// 获取已注册的类的列表,以下代码为官方提供使用案例
    int numClasses;
    Class * classes = NULL;
    classes = NULL;
    numClasses = objc_getClassList(NULL, 0);
    if(numClasses > 0){
        /// 开内存
        classes = (Class *)realloc(classes, sizeof(Class) * numClasses);
        numClasses = objc_getClassList(classes, numClasses);
        for (int i = 0; i < numClasses; i++) {
            const char *className = class_getName(classes[i]);
//            NSLog(@"%s", className);
        }

    }
    free(classes);

    /// 获取已注册的类比上面的省事
    unsigned int outCount;
    Class *copyClasses = objc_copyClassList(&outCount);
    for (int i = 0; i < outCount; i++) {
        const char *className = class_getName(classes[i]);
//            NSLog(@"%s", className);
    }

    /// 通过类名获取类,   objc_getClass,objc_lookUpClass,objc_getRequiredClass,作用一样,但是注意📢objc_getRequiredClass这个更危险,找不到会杀死当前进程
    Class lookUpClass = objc_lookUpClass("DDCollectionCycleController");
    Class tmp = objc_getRequiredClass("DDCollectionCycleController");
    
    /// 获取元类对象,通过终端发现元类是NSObject
    id meta = objc_getMetaClass("UIViewController");
    /// po meta
    /// UIViewController

    /// e object_getClass(meta)
    /// (Class _Nullable) $1 = 0x0000000229060db0
    /// (lldb) po $1
    /// NSObject

    /// 获取实例对象的name
    char * ivar_name = ivar_getName(personIvar);
    
    /// 获取实例对象的编码方式
    char *ivar_type = ivar_getTypeEncoding(personIvar);
    
    /// 创建关联对象
    objc_setAssociatedObject(person, @"user_name", @"DDS", OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    /// 获取关联对象的值
    id user_name = objc_getAssociatedObject(person, @"user_name");
    /// 删除obj全部关联对象
    /// objc_removeAssociatedObjects(person);
    
    /// 消息发送objc_msgSend,这种写法需要引入<objc/message.h>,他还有好几个兄弟,不一一介绍
    ((void (*)(id, SEL, NSString *))(void *)objc_msgSend)((id)self, sel_registerName("test1:"),@"");
    
    
    /// 方法调用
    /// method_invoke
    /// 择日继续更新
    
    
    
    
    NSLog(@"%s",className);
    
}

+ (void)classMethod {
    
}
- (void)originMethod {
    
}
- (void)swizzMethod {
    
}
- (void)test1:(NSString *)t {
    
}

id getter(id self, SEL _cmd) {
    NSString *key = [NSString stringWithFormat:@"_%@",NSStringFromSelector(_cmd)];
    Ivar ivar = class_getInstanceVariable([self class], key.UTF8String);
    id value = object_getIvar(self, ivar);
    return value;
}

void setter(id self, SEL _cmd, id newValue) {
    //移除set
    NSString *key = [NSStringFromSelector(_cmd) stringByReplacingCharactersInRange:NSMakeRange(0, 3) withString:@""];
    //首字母小写(不支持开发者故意把属性名称首字母大写的可能)
    NSString *head = [key substringWithRange:NSMakeRange(0, 1)];
    head = [head lowercaseString];
    key = [key stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:head];
    //移除后缀 ":"
    key = [key stringByReplacingCharactersInRange:NSMakeRange(key.length - 1, 1) withString:@""];
    Ivar ivar = class_getInstanceVariable([self class], [NSString stringWithFormat:@"_%@",key].UTF8String);
    object_setIvar(self, ivar, newValue);
}

相关文章

网友评论

      本文标题:iOS RunTime常用内容总结

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