runtime 学习一下

项目终于忙完了 ,可以有点儿时间 学习一下 ,学习的runtime 记录一下 ,自己敲了一遍,感觉到更加亲切了点儿,话不多说。直接上代码了。

一 动态创建类对象

 // 继承类   类名字   是否需要扩展
Class Person = objc_allocateClassPair([NSObject class], "Person", 0);
 //添加成员变量 
 //类 、 名字 、 大小、 补齐方式 、 对应的编码(这个是苹果的一个列表)
class_addIvar(Person, "_age", sizeof(int), 1, @encode(int));
 //添加方法
class_addMethod(Person, @selector(run), (IMP)run, "v@:");
 //一定要再注册之前,把成员变量 或者属性加上
objc_registerClassPair(Person);
// 实例化对象 进行测试
id student = [[Person alloc] init];
[student setValue:@1 forKey:@"_age"];
NSLog(@"%@",[student valueForKey:@"_age"]);

二 查看对象的属性 和 成员变量

//查看成员变量
unsigned int number = 0;
Ivar *ivars = class_copyIvarList(Person, &number);
//查看属性 
unsigned int count;
class_copyPropertyList(Person, &count);

大家一定对此也有疑问,感觉这两个也差不多 , 但是是有差别的,class_copyPropertyList 这个方法只能获取@property 声明的属性,然而 ivar 就可以获取所有的成员变量和属性 _age这类。
当然 获取完属性 我们就可以进行转换成 字符串

    for (int i = 0; i <number; i++) {
      const char *name = ivar_getName(ivars[i]);
      NSString *update = [NSString stringWithUTF8String:name];
    //  NSString *name = [NSString      stringWithUTF8String:property_getName(propertys[i])];
//        NSLog(@"%@",name);
  } 

这样就可以转换成字符串了,这样就有了功能 ,
1.可以进行赋值 也就是model 避免了过多空间的浪费,有几个属性,就需要几个值
2.可以进行归档,解档,如下

 -(void)encodeWithCoder:(NSCoder *)aCoder {
   unsigned int number = 0;
   Ivar *ivarLists = class_copyIvarList([self class], &number);
for (int i = 0; i < number; i++) {
       const char *name = ivar_getName(ivarLists[i]);
       NSString *realName = [NSString stringWithUTF8String:name];
       NSString *value = [self valueForKey:realName];
       [aCoder encodeObject:value forKey:realName];
    }
  }

 -(instancetype)initWithCoder:(NSCoder *)aDecoder {

unsigned int number = 0;
Ivar *ivarLists = class_copyIvarList([self class], &number);
for (int i = 0; i < number; i++) {
    const char *name = ivar_getName(ivarLists[i]);
    NSString *realName = [NSString stringWithUTF8String:name];
    NSString *value = [aDecoder decodeObjectForKey:realName];
    [self setValue:value forKey:realName];
    
}
return self;

}

三 动态添加方法

当我们动态添加方法之后 ,因为没有实现方法 所以会走如下的方法, 在这个里面 我们进行拦截,告诉程序 实现方法的 imp指针在哪里, imp指针就是 实现方法的地址。(这个是实例对象的方法找不到调用的方法,还有一个是类的方法)

  +(BOOL)resolveInstanceMethod:(SEL)sel {
  if ([NSStringFromSelector(sel) isEqualToString:@"foo:"]) {
    class_addMethod(self, sel, (IMP)haha, "v@:");
    return YES;
   }
   return [super resolveInstanceMethod:sel];
  }

大家注意 这个格式 , 首先是 obj 就是对象, sel 是方法(就是你调用的方法,但是没有) objc 是参数。 只有遵守格式才能调用到这个方法

void haha(id obj,SEL sel,NSString * objc){
   NSLog(@"%@--%@--  %@",obj,NSStringFromSelector(sel),objc);
}

四 方法交换 、替换

SEL mySel = @selector(eat);
SEL originSel = @selector(viewDidLoad);
Method originMethod = class_getInstanceMethod([self class], originSel);
Method newMethod = class_getInstanceMethod([self class], mySel);
 交换方法
 method_exchangeImplementations(myMethod, cusMethod);
 方法替换
 class_replaceMethod([self class], mySel, method_getImplementation(myMethod), method_getTypeEncoding(myMethod));

五。绑定对象
在刚开始开发的时候,碰见有很多 btn的实现方法都是block 方法实现,看了里面的代码 也不懂,当时毕竟是个菜菜---哈哈。
今天就解答一下 绑定的问题,一般是在set 和 get的时候用到的比较多:
在绑定的时候 调用该方法,此处掉了weak的 方法

   objc_setAssociatedObject(self, (__bridge const void *)@"zsl", object, OBJC_ASSOCIATION_ASSIGN);

当需要取出的时候

   id object = objc_getAssociatedObject(self, (__bridge const void *)@"zsl");

就比如 我们在扩展类中 给对象 创建了成员变量很方便

六 发送消息
oc代码的方法的调用 就是发送消息 就比如 我们要 alloc init 一个对象。

   [[Person alloc] init];

转换成底层代码

Person *  pOne = objc_msgSend(objc_getClass("Person"), sel_registerName("alloc"));
objc_msgSend(pOne, @selector(init));

七 关于kvo
关于kvo ,实质是在addObserver 的方法中 创建了该对象的子类,并且 对 self 进行了一个转类, 转成了子类,之后就是重写set 方法,
以下是自定义的监听

-(void)zsl_AddObserver:(NSObject *)object forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context Block:(Block)smallBlock {

NSString *myClassName = [NSString stringWithFormat:@"NewCar"];
Class myClass = objc_allocateClassPair([self class], myClassName.UTF8String, 0);
//完成注册
objc_registerClassPair(myClass);

//转类
object_setClass(self, myClass);

//重写 setname 方法
class_addMethod(myClass, @selector(setName:), (IMP)setName,"v@:@");
//绑定控制器  此处的 object 就是监听对象
objc_setAssociatedObject(self, (__bridge const void *)@"zsl", object, OBJC_ASSOCIATION_ASSIGN);
//绑定控制器   block 方式
objc_setAssociatedObject(self, (__bridge const void *)@"zsl_block", smallBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

下面就是 重写的set方法 ,回调方式有2中 一种是block 的 一种就是 调用方法的 Block中的参数 就是 回调中需要的参数

 void setName(id self, SEL _cmd, NSString *newName) {
//    NSLog(@"%@",newName);

struct objc_super Car = {self,class_getSuperclass([self class])};
objc_msgSendSuper(&Car, _cmd,newName);
    id object = objc_getAssociatedObject(self, (__bridge const void *)@"zsl");
 //    objc_msgSend(object,    @selector(observeValueForKeyPath:ofObject:change:context:),       @"name",self,@{@"name":newName},nil);

Block  block = (Block) objc_getAssociatedObject(self, (__bridge const void *)@"zsl_block");
block(@"name", object, @{@"name":newName});


 }

仅是自己的学习记录,如果有错误之处,望指出,进行修改!!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,034评论 1 32
  • 1.ios高性能编程 (1).内层 最小的内层平均值和峰值(2).耗电量 高效的算法和数据结构(3).初始化时...
    欧辰_OSR阅读 29,012评论 8 265
  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,633评论 0 9
  • OC语言基础 1.类与对象 类方法 OC的类方法只有2种:静态方法和实例方法两种 在OC中,只要方法声明在@int...
    奇异果好补阅读 4,192评论 0 11
  • 那一年我们正青春 你爱你的周杰伦 我爱我的莫文蔚 那年离我们好远 远的都无法触碰 那年离我们好近 近的就像昨天 走...
    美丽小花的猪阅读 260评论 0 2