美文网首页iOS
iOS通过runtime给分类添加属性

iOS通过runtime给分类添加属性

作者: _清墨 | 来源:发表于2019-03-27 13:38 被阅读0次
分类Category可以添加方法,但不能直接添加属性,如下,我们创建一个UIImage的Category: WX20190327-130805@2x.png
WX20190327-130820@2x.png

咱们直接输入一个Url,最终得到的是:


image.png

这样一个分类,我们给其添加一个属性:

@property (nonatomic, copy) NSString *imageUrl;

这是编译一下,会报如下警告


image.png

而且如果这时在外部使用这个属性,运行会crash,并会报如下错误

调用set方法时
2019-03-27 13:18:03.497364+0800 Target[98782:2455630] *** 
Terminating app due to uncaught exception 'NSInvalidArgumentException', 
reason: '-[UIImage setImageUrl:]: 
unrecognized selector sent to instance 0x600002bc8ee0'
调用get方法时
2019-03-27 13:19:49.208647+0800 Target[98819:2456879] *** 
Terminating app due to uncaught exception 'NSInvalidArgumentException', 
reason: '-[UIImage imageUrl]: 
unrecognized selector sent to instance 0x600002950230'

原因就是这个分类属性找不到set和get方法,若要能正常使用这个属性的set和get方法,我们可以通过runtime来做到:

首先我们在.m里

#import <objc/runtime.h>

然后重写set和get方法

-(void)setImageUrl:(NSString *)imageUrl{
    
}

-(NSString *)imageUrl{
    
}

这时需要了解的函数是

//set
objc_setAssociatedObject(<#id  _Nonnull object#>, <#const void * _Nonnull key#>, <#id  _Nullable value#>, <#objc_AssociationPolicy policy#>)
//get
objc_getAssociatedObject(id _Nonnull object, const void * _Nonnull key)

set有四个参数,get的参数可以参考set
1.源对象(self)
2.关联时的用来标记的key(因为可能会添加很多属性,我们这里是imageUrl,所以也需要一个imageUrl的key:& imageUrl_key)

//我们需要在.m里声明这个key
static NSString *imageUrl_key = @"imageUrl_key";

3.关联的对象(imageUrl)
4.一个关联策略(OBJC_ASSOCIATION_COPY)。

typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
    OBJC_ASSOCIATION_ASSIGN = 0,             //关联对象的属性是弱引用    
    OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1,   //关联对象的属性是强引用并且关联对象不使用原子性
    OBJC_ASSOCIATION_COPY_NONATOMIC = 3,     //关联对象的属性是copy并且关联对象不使用原子性
    OBJC_ASSOCIATION_RETAIN = 01401,         //关联对象的属性是copy并且关联对象使用原子性
    OBJC_ASSOCIATION_COPY = 01403            //关联对象的属性是copy并且关联对象使用原子性
};

最终的set和get方法是这样的

-(void)setImageUrl:(NSString *)imageUrl{
    objc_setAssociatedObject(self, &imageUrl_key, imageUrl, OBJC_ASSOCIATION_COPY);
}

-(NSString *)imageUrl{
    return objc_getAssociatedObject(self, &imageUrl_key);
}

这时在外部就能正常使用这个属性:

UIImage *image = [[UIImage alloc]init];
image.imageUrl = @"www.999999.com";
    
NSString *url = image.imageUrl;

相关文章

  • iOS关联对象技术原理

    iOS 通过 runtime 的 API 可以给分类添加属性,关联属性总共有下边3个 API 通过 runtime...

  • iOS runtime 动态添加属性,方法,方法交换案例

    iOS runtime 动态添加属性,方法,方法交换案例 动态添加属性 我之前写过分类的文章,说过,分类不能添加成...

  • Runtime为分类添加属性-2021-02-24-周三

    正常情况下,分类可以添加方法,但是不能添加属性;通过runtime的关联对象,可以实现分类添加属性的目的; 分类头...

  • runtime

    最近在研究runtime,所以就简单记录下我的一些收获吧算是 利用runtime通过分类添加类属性 iOS类扩展:...

  • iOS通过runtime给分类添加属性

    咱们直接输入一个Url,最终得到的是: 这样一个分类,我们给其添加一个属性: 这是编译一下,会报如下警告 而且如果...

  • 在iOS中分类和类中添加属性和方法的区别

    分类和类都可以添加方法和属性 属性分类通过runtime添加属性类直接添加 方法添加方式一样 生成 类中生成的有:...

  • ios 利用runtime给分类动态添加属性

    1、分类默认是不能添加属性的,这里我们用runtime实现给分类添加属性,本例给UIView添加一个string属...

  • runtime相关

    修改系统方法 动态添加方法 动态给系统类添加属性(给分类添加属性) runtime+kvc 转换模型

  • runtime 分类不能添加属性

    分类不能添加属性,类别可以,添加runtime之后,可以添加属性

  • 关联对象

    分类、类扩展、继承的总结讲述了分类,介绍到分类可以添加属性,但是属性的get、set方法需要通过runtime的关...

网友评论

    本文标题:iOS通过runtime给分类添加属性

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