Ivar(per, ivv, @"Mike"); //name属性Tom被强制改为Mike。
NSLog(@"改变之后的person:%@",per); }
点击按钮后,控制台输出:
2016-05-19 22:45:05.125 runtime运行时[1957:34730] 改变前的person:name:Tom age:12
2016-05-19 22:45:05.126 runtime运行时[1957:34730] 改变之后的person:name:Mike age:12
4.为person的category类增加一个新属性:
如何在不改动某个类的前提下,添加一个新的属性呢?
答:可以利用runtime为分类添加新属性。
在iOS中,category也就是分类,是不可以为本类添加新的属性的,但是在runtime中我们可以使用对象关联,为person类进行分类的新属性创建:
①新建一个新的OC类:
命名为:PersonCategory ,点击next:
②在出现的新类“person+PersonCategory.h”中,添加“height”:
#import "person.h"
@interface person (PersonCategory) @property (nonatomic,assign)float height; //新属性 @end
“person+PersonCategory.m”类的代码如下:
#import "person+PersonCategory.h"
#import <objc/runtime.h> //runtime API的使用需要包含此头文件
const char * str = "myKey"; //做为key,字符常量 必须是C语言字符串;
@implementation person (PersonCategory)
-(void)setHeight:(float)height{
NSNumber *num = [NSNumber numberWithFloat:height];
/*
第一个参数是需要添加属性的对象;
第二个参数是属性的key;
第三个参数是属性的值,类型必须为id,所以此处height先转为NSNumber类型;
第四个参数是使用策略,是一个枚举值,类似@property属性创建时设置的关键字,可从命名看出各枚举的意义;
objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);
*/
objc_setAssociatedObject(self, str, num, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
//提取属性的值:
-(float)height{
NSNumber *number = objc_getAssociatedObject(self, str);
return [number floatValue];
}
@end
接下来,我们可以在ViewController.m中对person的一个对象进行height的访问了,
将第四个按钮关联到ViewController.h添加行为并命名其方法为:“addVariable”:(记得:#import "person+PersonCategory.h")
- (IBAction)addVariable:(UIButton *)sender;
在ViewController.m中的实现如下:
/* 4.添加新的属性*/
- (IBAction)addVariable:(UIButton *)sender { per.height = 12; //给新属性height赋值
NSLog(@"%f",[per height]); //访问新属性值
}
点击按钮四、再点击按钮一、二获取类的属性、方法。
2016-05-20 15:39:54.432 runtime运行时[4605:178974] 12.000000
2016-05-20 15:39:56.295 runtime运行时[4605:178974] (Name: name) ----- (Type:@"NSString") 2016-05-20 15:39:56.296 runtime运行时[4605:178974] (Name: _age) ----- (Type:i) 2016-05-20 15:39:57.195 runtime运行时[4605:178974] (Method:func1) 2016-05-20 15:39:57.196 runtime运行时[4605:178974] (Method:func2) 2016-05-20 15:39:57.196 runtime运行时[4605:178974] (Method:setAge:) 2016-05-20 15:39:57.196 runtime运行时[4605:178974] (Method:age) 2016-05-20 15:39:57.196 runtime运行时[4605:178974] (Method:.cxx_destruct) 2016-05-20 15:39:57.197 runtime运行时[4605:178974] (Method:description) 2016-05-20 15:39:57.197 runtime运行时[4605:178974] (Method:init) 2016-05-20 15:39:57.197 runtime运行时[4605:178974] (Method:height) 2016-05-20 15:39:57.197 runtime运行时[4605:178974] (Method:setHeight:)
分析:可以看到分类的新属性可以在per对象中对新属性height进行访问赋值。
获取到person类属性时,依然没有height的存在,但是却有height和setHeight这两个方法;因为在分类中,即使使用@property定义了,也只是生成set+get方法,而不会生成_变量名,分类中是不允许定义变量的。
使用runtime中objc_setAssociatedObject()和objc_getAssociatedObject()方法,本质上只是为对象per添加了对height的属性关联,但是达到了新属性的作用;
使用场景:假设imageCategory是UIImage类的分类,在实际开发中,我们使用UIImage下载图片或者操作过程需要增加一个URL保存一段地址,以备后期使用。这时可以尝试在分类中动态添加新属性MyURL进行存储。
5.为person类添加一个新方法;
将第五个按钮关联到ViewController.h,添加行为并命名其方法为:“addMethod”:
- (IBAction)addMethod:(UIBu