zoukankan      html  css  js  c++  java
  • Runtime基本知识记录

    1.category使用 objc_setAssociatedObject/objc_getAssociatedObject 实现添加属性

    属性 其实就是get/set 方法。我们可以使用  objc_setAssociatedObject/objc_getAssociatedObject  实现 动态向类中添加 方法,在分类中导入

    #import <objc/runtime.h>

    @interface NSObject (CategoryWithProperty)
    
    @property (nonatomic, strong) NSObject *property;
    
    @end
    
    @implementation NSObject (CategoryWithProperty)
    
    - (NSObject *)property {
        return objc_getAssociatedObject(self, @selector(property));
    }
    
    - (void)setProperty:(NSObject *)value {
        objc_setAssociatedObject(self, @selector(property), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    
    @end

    2.重组系统的方法(method swizzling oc的黑魔法)

    如果对Runtime有一定了解的话,一定听说过或者用过这个函数:

    void method_exchangeImplementations(Method m1, Method m2)

    它通常叫做method swizzling,算是ObjC的"黑魔法"了,作用就是在程序运行期间动态的给两个方法互换实现,比如有这样一种使用场景:

    我们的程序中有许多个ViewController,我想在对项目改动最小的情况下,在当每个Controller执行完ViewDidLoad以后就在控制台把自己的名字打印出来,方便我去做调试或者了解项目结构。

    有许多朋友会这样说,让所有控制器都继承一个BaseController不就可以了吗?我在这里要解释一下这样做的缺点:假如你的项目里有许多Controller的话,你就需要把项目里凡是没有继承自BaseController的每个Controller都做一次修改了,而且随意更改层级结构会发生意想不到的错误。

    其实我们的目的就是重写ViewDidLoad的方法,并在他的方法最后加上几句Log,所以我们需要给UIViewController建立一个category,因为我们知道,如果在Catagory中重写一个方法,就会覆盖它的原有方法实现,但是,这样做以后就没有办法调用系统原有的方法,因为在一个方法里调用自己的方法会是一个死循环。所以我们的解决办法就是,另外写一个方法来和viewDidLoad“交换”,这样外部调用viewDidLoad就会调到新建的这个方法中,同样,我们调用新建的方法就会调用到系统的viewDidLoad中了。

    +(void)load{

                static dispatch_once_t onceToken;

            dispatch_once(&onceToken, ^{

                //获取到这个累的viewDidLoad方法,他的累心是一个object_method结构体的指针

                Method viewDidLoad = class_getInstanceMethod(self, @selector(viewDidLoad));

                //获取自己刚刚新建的方法

                Method viewDidLoaded = class_getInstanceMethod(self, @selector(viewDidLoaded));

                method_exchangeImplementations(viewDidLoad, viewDidLoaded);

            });

    }

    //新建一个方法与viewDidLoad交换

    -(void)viewDidLoaded{

        [self viewDidLoaded];

        NSLog(@"cuihongbao");

    }


    其他常用API:

    //
    向类中添加Method BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types) //修改类的Method IMP class_replaceMethod(Class cls, SEL name, IMP imp, const char *types) //交换2个方法中的IMP void method_exchangeImplementations(Method m1, Method m2) //获取类的某个实例方法 Method class_getInstanceMethod(Class aClass, SEL aSelector);

    注释:

    1、_cmd

    在Apple的官方介绍里看到轻描淡写的说了一句:“The _cmd variable is a hidden argument passed to every method that is the current selector”,其实说的就是_cmd在Objective-C的方法中表示当前方法的selector,正如同self表示当前方法调用的对象实例一样。

        比如,我们要打印当前要调用的方法,可以这样来写:

    - (void)viewDidLoad
    
        {
    
        [super viewDidLoad];
    
        NSLog(@"Current method: %@ %@",[self class],NSStringFromSelector(_cmd));
    
        }
    
        输出结果如下:
    
        TestingProject[570:11303] Current method: FirstViewController viewDidLoad
  • 相关阅读:
    uboot的Makefile分析
    S3C2440上触摸屏驱动实例开发讲解(转)
    linux嵌入式驱动软件开发(csdnblog)
    [连接]研究MSN的一些参考资料(MSNP15)
    关于Asp.net中使用以下代码导出Excel表格的问题
    FCKEditor在Asp.net的安装
    奥运后,接手两个项目,PECT培训,CIW培训,系分考试...........一堆流水帐
    [转]甩掉数据字典,让Sql Server数据库也来一个自描述
    SQL Server 调优将会用到的非常好的DMV
    SQL Server 监视数据文件大小变化
  • 原文地址:https://www.cnblogs.com/tangaofeng/p/5069345.html
Copyright © 2011-2022 走看看