zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    IDEA 工具使用报错总结
    Struts2 值栈总结(ValueStack)
    hibernate 中映射关系配置
    Java 注解之总结
    ssh_整合总结
    Ajax 请求之_请求类型详解
    C++的重载赋值运算符
    vector容器使用reserve预留空间
    C++中的内存分配
    C++ const修饰指针
  • 原文地址:https://www.cnblogs.com/ly1973/p/9020624.html
Copyright © 2011-2022 走看看