runtime 内涵篇

 

1 消息发送机制

/
//  ViewController.m
//  001--消息机制
//
//  Created by H on 2017/11/2.
//  Copyright © 2017年 H. All rights reserved.
//

#import "ViewController.h"
#import "Person.h"
#import "HKPerson.h"
#import <objc/message.h>


@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    HKPerson * p = [[HKPerson alloc] init];
    

    //给父类发消息
    /*
     1.objc_super 结构体指针!
     2.方法编号
     */
    //class_getSuperclass 获取父类类型
    //定义objc_super 结构体
   /*
    struct objc_super {
        __unsafe_unretained _Nonnull id receiver;//当前对象

        __unsafe_unretained _Nonnull Class super_class;//父类类型

    };
    */
    //子类调用 父类方法 HKPerson调用父类person的 eatWith: 方法
    struct objc_super hksuper = {p,class_getSuperclass(objc_getClass("HKPerson"))};
    //给父类发消息
    
    objc_msgSendSuper(&hksuper, @selector(eatWith:),@"汉堡");
}

-(void)demo1
{
    //alloc  :分配内存空间  malloc()用来分配内存的!! 告诉系统.给我一块空间!!
    

    //    Person * p = [[Person alloc] init];
    
    //OC的方法中: 1.SEL 方法编号
    //    NSClassFromString(@"Person");
    //objc_getClass("Person");
    
    //    Person * p = [Person alloc];
    Person * p = objc_msgSend(objc_getClass("Person"), sel_registerName("alloc"));
    //    p = [p init];
    p = objc_msgSend(p, sel_registerName("init"));
    
    //    [p eatWith:@"汉堡!!"];
    
    objc_msgSend(p, sel_registerName("eatWith:"),@"汉堡!!");
}

/*
 总结
 发消息
 objc_msgSend( id  _Nullable self ,  SEL  _Nonnull op, ... )
 
 1 当前对象(可以是类 就是类对象)
 2 sel 方法编号
 
 
 
 */

@end

 2 动态添加方法 防止程序崩溃

//
//  Person.m
//  004--动态添加方法
//
//  Created by H on 2017/11/2.
//  Copyright © 2017年 H. All rights reserved.
//

#import "Person.h"
#import <objc/runtime.h>

@implementation Person

/*
 OC的方法调用,会传递默认两个隐世参数!给IMP(方法实现)!!
 objc_msgSend(self,_cmd);
 id self    方法调用者!
 SEL _cmd   方法编号!
 
 */


//如果该类接收到一个没有实现的实例方法,就会来到这里
+(BOOL)resolveInstanceMethod:(SEL)sel
{
//    NSLog(@"%@",NSStringFromSelector(sel));
    //动态添加一个方法!!
    /*
     1.cls  调用方法所属类 Class  _Nullable __unsafe_unretained cls
     2.SEL  方法名称(方法编号)      SEL  _Nonnull name (sel--imp一一对应)
     3.IMP  方法实现的指针 IMP  _Nonnull imp
     4.types 返回值类型! const char * _Nullable types
     */
//    class_addMethod(Class  _Nullable __unsafe_unretained cls, SEL  _Nonnull name, IMP  _Nonnull imp, const char * _Nullable types)
    class_addMethod(self, sel, (IMP)haha, "v@:@");
    
    return [super resolveInstanceMethod:sel];
}

void haha(id obj,SEL sel,NSString * objc){
    NSLog(@"%@--%@--%@",obj,NSStringFromSelector(sel),objc);
}
/*
 总结:
 1 view调用 person方 eat:方法 但是Person并没有实现这个方法
   [p performSelector:@selector(eat:) withObject:@"汉堡!!"];
 2 Person类 在runtime中 如果方法找不到会调用
 +(BOOL)resolveInstanceMethod:(SEL)sel(仅仅实例方法)
 3 方案 动态添加方法
 void haha(id obj,SEL sel,NSString * objc){}
 注意 为什么 不是 void haha(NSString * objc){}
 因为 objc_msgSend(self,_cmd); 消息接受者/方法编号 传递给imp(指向函数的指针)
 所以 加上字符串参数 一共是三个
 */
@end

 

posted @ 2018-05-10 17:13  看谷秀  阅读(132)  评论(0编辑  收藏  举报