zoukankan      html  css  js  c++  java
  • RunTime 运行时

    简单介绍RunTime 运行时的用法

    以下操作都需要导入头文件

    #import <objc/message.h>

    #pragma mark -- 发消息


    //OC方法调用的本质就是让对象发消息
    Person * p = [[Person alloc] init];

    //[p eat];//底层是发消息

    //对象方法
    objc_msgSend(p, @selector(eat)); 

     //类方法

    [Person eat];

    //类方法
    objc_msgSend([Person class], @selector(eat));

    #pragma mark -- 交换换方法的实现

    目的:当你调用系统方法的时候,为系统自带的方法增加一些特有的功能!

    //1、创建方法所属的类的分类

    //创建URL的分类

    + (void)load

    {//当这个类被加载进内存的时候调用这个方法,执行一次
      //交换方法的实现 根据方法标号 找到对应的返回实现,交换实际执行的方法
      Method systemURLWithString = class_getClassMethod([NSURL class], @selector(URLWithString:));

      Method myURLWithString = class_getClassMethod([NSURL class], @selector(my_URLWithString:));

      method_exchangeImplementations(systemURLWithString, myURLWithString);
    }

    //实现自己的方法

    + (nullable instancetype)my_URLWithString:(NSString *)URLString;
    {
      //实际会走系统的URLWithString方法
      NSURL * url = [NSURL my_URLWithString:URLString];
      if (url == nil) {
        NSLog(@"url有问题");//做一些需要特殊处理的操作
        return nil;
      }
      return url;
    }

    #pragma mark - 动态的增加方法

    //一个类调用了一个没有实现的类方法时,就会调用这个方法

    //没有返回值
    void aaa(id self, SEL _cmd, id param) {
      NSLog(@"%@ %@ %@", self, NSStringFromSelector(_cmd), param);
    }


    //sel:没有实现的方法

    + (BOOL)resolveClassMethod:(SEL)sel
    {
      if (sel == @selector(eat:)) {
      // cls: 给哪一个类添加方法 SEL:方法标号 IMP:方法实现 types:方法类型
      //"v@:" --> v代表void @代表id类型对象 :代表SEL
      class_addMethod(self, sel, (IMP)aaa, "v@:@");
      return YES;
    }
    return [super resolveClassMethod:sel];
    }


    //一个类调用了一个没有实现的对象方法时,就会调用这个方法
    + (BOOL)resolveInstanceMethod:(SEL)sel
    {
      return return [super resolveInstanceMethod:sel];
    }

    #pragma mark - 动态的增加属性 

    // 1、创建分类

    .h中增加属性 

    @property (nonatomic, copy) NSString * name;

    // 注意:给分类增加属性只会生成setter和getter的方法声明,不会生成setter和getter的实现,也不会生成下划线开头的的成员变量,需要自己实现set和get方法,否则调用的时候就会崩溃,崩溃原因:找不到set和get的方法实现!!!解决办法:利用运行时,动态的实现set和get方法

    - (void)setName:(NSString *)name
    {
    /*
    * id object 给哪个对象的属性赋值
    const void *key 属性对应的key
    id value 设置属性值为value
    objc_AssociationPolicy policy 使用的策略
    objc_setAssociatedObject(<#id object#>, <#const void *key#>, <#id value#>, <#objc_AssociationPolicy policy#>)
    */
    objc_setAssociatedObject(self, @"name", name, OBJC_ASSOCIATION_COPY_NONATOMIC);

    }

    - (NSString *)name
    {
    return objc_getAssociatedObject(self, @"name");
    }

    #pragma mark -- 查找子类方法


    + (NSArray *)findAllSubClassofClass:(Class)superClass
    {
      int count = objc_getClassList(NULL, 0);

      NSMutableArray *output = [NSMutableArray array];

      if (count <= 0) {//发生错误或者没有子类

        @throw @"Couldn't retrieve Obj-C class-list";
        return output;
      }

      Class *classes = (__unsafe_unretained Class *)malloc(sizeof(Class) * count);

      count = objc_getClassList(classes, count);

      for (int i = 0; i < count; ++i) {

        if (superClass == class_getSuperclass(classes[i])) {//子类

          [output addObject:classes[i]];
        }
      }
      //释放C 语言的对象
      free(classes);

      return output;
    }

     更多内容--> 博客导航 每周一篇哟!!!

    有任何关于iOS开发的问题!欢迎下方留言!!!或者邮件lieryangios@126.com 虽然我不一定能够解答出来,但是我会请教iOS开发高手!!!解答您的问题!!!

  • 相关阅读:
    编码导致 html和aspx 样式差异,变形
    Recommand of the Day:Names in English
    NSBundle常用方法及解释
    在K8S 中部署 Spring Boot 应用,爽!
    如果抛开 Spring,如何自己实现 AOP?面试必问。。。
    为什么阿里强制 boolean 类型变量不能使用 is 开头?
    CTO 说禁用 Lombok,看我怼死他。。
    面试官:什么是 YAML?和 Spring Boot 有什么关系?
    面试官:线程池多余的线程是如何回收的?
    JetBrains 发布下一代 IDE,无比轻量,几秒就能启动干活,IDEA 可以扔了。。
  • 原文地址:https://www.cnblogs.com/CoderEYLee/p/Object-C-0020.html
Copyright © 2011-2022 走看看