zoukankan      html  css  js  c++  java
  • ios开发runtime学习三:动态添加方法(实际应用少,面试)

    #import "ViewController.h"
    #import "Person.h"
    
    /* 
        1:
        Runtime(动态添加方法):OC都是懒加载机制,只要一个方法实现了,就会马上添加到方法列表中.
        app:免费版,收费版
        QQ,微博,直播等等应用,都有会员机制
        performSelector:去执行某个方法。performSelector withObject :object为前面方法的参数
        
        2:
        美团有个面试题?有没有使用过performSelector,什么时候使用?动态添加方法的时候使用过?怎么动态添加方法?用runtime?为什么要动态添加方法?
     */
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
    //    _cmd:当前方法的方法编号
        
        Person *p = [[Person alloc] init];
        
        // 执行某个方法
    //    [p performSelector:@selector(eat)];
        
        [p performSelector:@selector(run:) withObject:@10];
        
    
    }
    
    @end
    #import "Person.h"
    #import <objc/message.h>
    
    @implementation Person
    
    // 没有返回值,也没有参数
    // void,(id,SEL)
    void aaa(id self, SEL _cmd, NSNumber *meter) {
        
        NSLog(@"跑了%@", meter);
        
    }
    
    // 任何方法默认都有两个隐式参数,self,_cmd(_cmd代表方法编号,打印结果为当前执行的方法名)
    // 什么时候调用:只要一个对象调用了一个未实现的方法就会调用这个方法,进行处理
    // 作用:动态添加方法,处理未实现
    + (BOOL)resolveInstanceMethod:(SEL)sel
    {
        // [NSStringFromSelector(sel) isEqualToString:@"eat"];
        if (sel == NSSelectorFromString(@"run:")) {
            // eat
            // class: 给哪个类添加方法
            // SEL: 添加哪个方法
            // IMP: 方法实现 => 函数 => 函数入口 => 函数名
            // type: 方法类型:void用v来表示,id参数用@来表示,SEL用:来表示
            //aaa不会生成方法列表
            class_addMethod(self, sel, (IMP)aaa, "v@:@");
            
            return YES;
        }
        
        return [super resolveInstanceMethod:sel];
    
    }
    
    //- (void)test
    //{
    //    // [NSStringFromSelector(sel) isEqualToString:@"eat"];
    //    if (sel == NSSelectorFromString(@"eat")) {
    //        // eat
    //        // class: 给哪个类添加方法
    //        // SEL: 添加哪个方法
    //        // IMP: 方法实现 => 函数 => 函数入口 => 函数名
    //        // type: 方法类型
    //        class_addMethod(self, sel, (IMP)aaa, "v@:");
    //        
    //        return YES;
    //    }
    //    
    //    return [super resolveInstanceMethod:sel];
    //}
    @end

    ####3.动态添加方法

    * 开发使用场景:如果一个类方法非常多,加载类到内存的时候也比较耗费资源,需要给每个方法生成映射表,可以使用动态给某个类,添加方法解决。

    * 经典面试题:有没有使用performSelector,其实主要想问你有没有动态添加过方法。

    * 简单使用

    ```

    @implementation ViewController

    - (void)viewDidLoad {

        [super viewDidLoad];

        // Do any additional setup after loading the view, typically from a nib.

        

        Person *p = [[Person alloc] init];

        

        // 默认person,没有实现eat方法,可以通过performSelector调用,但是会报错。

        // 动态添加方法就不会报错

        [p performSelector:@selector(eat)];

        

    }

    @end

    @implementation Person

    // void(*)()

    // 默认方法都有两个隐式参数,

    void eat(id self,SEL sel)

    {

        NSLog(@"%@ %@",self,NSStringFromSelector(sel));

    }

    // 当一个对象调用未实现的方法,会调用这个方法处理,并且会把对应的方法列表传过来.

    // 刚好可以用来判断,未实现的方法是不是我们想要动态添加的方法

    + (BOOL)resolveInstanceMethod:(SEL)sel

    {

        

        if (sel == @selector(eat)) {

            // 动态添加eat方法

            

            // 第一个参数:给哪个类添加方法

            // 第二个参数:添加方法的方法编号

            // 第三个参数:添加方法的函数实现(函数地址)

            // 第四个参数:函数的类型,(返回值+参数类型) v:void @:对象->self :表示SEL->_cmd

            class_addMethod(self, @selector(eat), eat, "v@:");

            

        }

        

        return [super resolveInstanceMethod:sel];

    }

    @end

    ```

  • 相关阅读:
    Android用户界面UI组件--AdapterView及其子类(五) Spinner和SpinnerAdapter
    Android用户界面UI组件--AdapterView及其子类(四) GridView
    Android用户界面UI组件--AdapterView及其子类(三) ExpandableListView
    Android用户界面 UI组件--AdapterView及其子类(二) AdapterViewAnimator及其子类
    Navigation Drawer介绍
    Android用户界面 UI组件--AdapterView及其子类(一) ListView及各种Adapter详解
    draw9patch超详细教程
    主线程中有多个handler的情况
    Python服务器开发二:Python网络基础
    shell脚本实现无密码交互的SSH自动登陆
  • 原文地址:https://www.cnblogs.com/cqb-learner/p/5871481.html
Copyright © 2011-2022 走看看