美文网首页iOS开发攻城狮的集散地iOS开发
IOS 用Runtime给分类添加属性、方法

IOS 用Runtime给分类添加属性、方法

作者: 上帝是个女孩丶 | 来源:发表于2017-05-09 11:24 被阅读1219次

    分类的作用:可以在不修改原来类的基础上,为一个类扩展方法。该方法可以不写实现。

    扩展(extension)是category的一个特例,有时候也被称为匿名分类。他的作用是为一个类添加一些私有的成员变量和方法。多用于.m 

    @interface ViewController ()

    @end

    这就是最简单的扩展,扩展只介绍这么多。

    1.分类创建方法:

    分类创建完毕。

    我这里是创建了两个分类,一个用于测试公有,一个用于测试私有.

    说一下为什么创建两个,有时候会根据不同业务去创建不同的分类。或者类过大也会创建多个分类。

    接下来说下问题:

    1.分类与分类之间的方法和属性不能互相调用,但是都可以调用基类。

    2.分类中原则上只能添加私有属性,下面会讲到通过runtime添加公有属性。而且setter和getter方法需要手动实现。

    3.分类中方法名字重复的话会优先调用私有的。在本类和分类有相同的方法时,直接覆盖基类方法。

    如果有两个分类,他们都实现了相同的方法,如何判断谁先执行?分类执行顺序可以通过targets,Build Phases,Complie Source进行调节,注意执行顺序是从上到下的。(只有两个相同方法名的分类)

    category 方法可能会覆盖于同一个类class 的其它 category 中的方法。但也可能被覆盖,因为不法预知他们的加载优先顺序,出现这种情况通常会在编译时出错。如果在一个开发的SDK中使用了类别, 就最好保证类别名不同于使用者的类别名,以及类别方法也不同于使用者的类别方法名, 通常通过加前缀来做到。

    注意:这里经过测试,分类的调用跟创建(添加进项目)时间有关,跟调用顺序无关。如果多个分类方法名冲突,会调用最后创建的那一个,前面会被覆盖。(更正一下,创建不是指创建时间,而是指加入项目的时间,即便你去年就创建了分类A,现在创建了分类B。然后先加入B,后加入A。调用的方法还是优先调用A)

    另外一点,试验证明,你创建了分类,即便头文件不引入,只要方法名相同,还是会调用后来创建的。因为这代表调用了私有方法。

    (这个结论是亲自测试的,网上搜半天并没有得到什么有用的答案。还是自己亲自来靠谱)

    4.分类的方法优先级高,但是不可以调用super方法。

    接下来介绍一下category添加属性。

    由于分类set get方法需要手动实现。所以直接实现方法就行。

    这里分别是两种不同类型的属性,基本类型和对象类型。均使用runtime

    /*

    * id object 给哪个对象的属性赋值

    const void *key 属性对应的key

    id value  设置属性值为value

    objc_AssociationPolicy policy  使用的策略,是一个枚举值,和copy,retain,assign是一样的,IOS开发一般都选择NONATOMIC

    objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);

    */

    源对象,关联时的用来标记是哪一个属性的key(因为你可能要添加很多属性),关联的对象和一个关联策略。

    用来标记是哪一个属性的key常见有三种写法:

    static NSNumber *numKey;

    static void *numKey = &numKey;

    static char numKey;

    更新:

    分类的命名要尽量带前缀,方便区分。

    runtime  严谨写法:

    - (NSString*)YYURLString{

    return  objc_getAssociatedObject(self, ((__bridge void*)PageNavigationURLStringKey));

    }

    - (void)setYYURLString:(NSString*)urlString{

    objc_setAssociatedObject(self, ((__bridge void*)PageNavigationURLStringKey),urlString, OBJC_ASSOCIATION_RETAIN);

    }

    主要在于前面加了个__bridge void *    实现id类型与void*类型的相互转换。方便通用OC和C指针

    否则当遇到对象类型的时候会报错,当然了这个值一般是我们自己定义的,均为字符串。具体参考网址:http://blog.csdn.net/sanpintian/article/details/8139878

    拓展:这种利用Runtime赋值的方式,可以将某个对象赋值给某个类,相当于页面间传值,很强大。

    相关文章

      网友评论

      • Corbin___:为什么分类不能调用super方法
        上帝是个女孩丶:这个具体的没有仔细研究过,但是分类不同于子类。分类连添加公用属性的能力都不存在。也就是说其实不希望他是实例对象。不想他具备子类的能力。如果想调用super,就转子类吧

      本文标题:IOS 用Runtime给分类添加属性、方法

      本文链接:https://www.haomeiwen.com/subject/jsqvtxtx.html