Runtime消息传递和转发

/*
 SEL:类成员方法的指针.SEL只是方法编号.
 
 IMP:函数指针,保存了方法地址.
 
 isa指针指向对象所属的类。
 
 someObject叫做接收者(receiver)。
 
 messageName叫做选择器(selector)
 
 选择器和参数合起来成为消息(message)
 
 消息派发系统:接收者类中找到和选择器名字相符的方法,就跳出递归寻找。如果没有找到,则在父类中找,以此类推,直到找到为止,如果都没有找到,就会开始进行消息转发。首先看下所属类,是否能动态添加方法,这个过程叫做“动态方法解析”
 
 
 消息机制原理:对象根据方法编号SEL去映射表查找对应的方法实现。
 
 
 */

#pragma mark -- 消息派送 --
void gotoSchool(id self,SEL cmd,id value) {
    printf("go to school");
    
}
//对象在收到无法解读的消息后,首先将调用所属类的该方法。
+ (BOOL)resolveInstanceMethod:(SEL)sel {
    NSString *selectorString = NSStringFromSelector(sel);
    if ([selectorString isEqualToString:@"gotoSchool"]) {
        //给当前类添加函数
        class_addMethod(self, sel, (IMP)gotoSchool, "@@:");
    }
    return [super resolveInstanceMethod:sel];
}
//当动态方法解析没有实现或者无法处理的时候,就会执行----备援接收者

- (id)forwardingTargetForSelector:(SEL)aSelector
{
    return self;//备援接者对象
}
//当动态方法解析和备援接收者都没有进行处理的话,就会执行----消息转发,如果消息转发再没有了,就会调用:doesNotRecognizeSelector报错信息,就崩溃了。
- (void)forwardInvocation:(NSInvocation *)anInvocation {
    NSLog(@"%@ can't handle by People",NSStringFromSelector([anInvocation selector]));
}
/*
 对一个你的对象不识别的消息进行相应,你必须重写methodSignatureForSelector:方法,该方法返回一个NSMethodSIgnature对象,该对象包含了给定选择器所标识方法的描述。主要包含返回值的信息和参数信息
 */
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    NSMethodSignature *sign = [NSMethodSignature signatureWithObjCTypes:"@@:"];
    return sign;
    
}
//获取所有属性list
-(void)funGetAllProperty
{
    unsigned int count = 0;
    objc_property_t *propertyList = class_copyPropertyList([LoginModel class], &count);
    for (unsigned int i = 0; i < count; i++) {
        const char *propertyName = property_getName(propertyList[i]);
        const char *caicai = property_getAttributes(propertyList[i]);
        NSLog(@"property----="">%s", caicai);
    }
    const char *name = "name";
    
    NSLog(@"property----="">%@", [NSString stringWithUTF8String:class_getProperty([LoginModel class], name)]);
}


#pragma mark -- 方法交换 动态加载--
-(void)functionOne
{
    NSLog(@"functionOne");
}

// 加载图片 且 带判断是否加载成功
-(void)functionTwo
{
    //不会死循环,由于交换了两个方法,所以调用ln_imageNamed其实是调用imageNamed。可以作为原方法的扩展
//    [self functionTwo];
    NSLog(@"functionTwo");
}
- (void)loadChange {
    // 1.获取方法地址
    // class_getClassMethod(获取某个类的方法)
    Method imageNamedMethod = class_getInstanceMethod([self class],@selector(functionOne));
    // 2.获取 ln_imageNamed方法地址
    Method ln_imageNamedMethod = class_getInstanceMethod([self class],@selector(functionTwo));
    // 3.交换方法地址,相当于交换实现方式;「method_exchangeImplementations 交换两个方法的实现」
    method_exchangeImplementations(imageNamedMethod, ln_imageNamedMethod);
}
 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值