1.访问私有变量
前面说过KVC可以设置私有变量的值,runtime同样可以。苹果没有真正意义上的私有变量
首先创建个model类
@interface Person ()
{
NSString *name;
}
@end
创建私有变量name
现在我想在外面访问这个name,并给其赋值,读取到值
Person *person = [[Person alloc] init];
Ivar *ivars = class_copyIvarList([Person class], &count);
for (int i = 0; i<count; i++) {
Ivar ivar = ivars[i];
//获取变量名
const char *varName = ivar_getName(ivar);
//获取变量类型
const char *type = ivar_getTypeEncoding(ivar);
// NSLog(@"%s -- %s", varName, type);
NSString *name = [NSString stringWithUTF8String:varName];
if ([name isEqualToString:@"name"]) {
//设置变量的值
object_setIvar(person, ivar, @"xiaoming");
//读取到变量的值
NSLog(@"%@", object_getIvar(person, ivar));
}
}
2.给分类(类目)添加属性
原理:给一个类声明属性,其实本质就是给这个类添加关联,并不是直接把这个值的内存空间添加到类内存空间
//定义关联的key
static const char *key = "sex";
@implementation Person (Property)
- (NSString *)sex
{
//根据关联的key,获得关联的值
return objc_getAssociatedObject(self, key);
}
- (void)setSex:(NSString *)sex
{
//第一个参数:给那个对象添加关联
//第二个参数:关联的key,通过这个key获取
//第三个参数:关联的value
//第四个参数:关联的策略
objc_setAssociatedObject(self, key, sex, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
当然方法在h进行声明
Person *person = [[Person alloc] init];
person.sex = @"男";
NSLog(@"%@", person.sex);
当然还可以添加方法,自己研究去吧
3 动态交换方法
比如要实现占位图的功能,在没有图片时始终显示占位图
@implementation UIImage (Extension)
//这里说明一下load方法,它是在类被引用时就会调用,和initialize有区别,initialize是在类或者其子类的第一个方法被调用前调用,所有即使类文件被引用,但是没有使用,那么initialize也不会被调用
+ (void)load
{
//交换方法
//获得imageWithName方法地址
Method imageWithName = class_getClassMethod(self, @selector(imageWithName:));
//获得imageNamed方法地址
Method imageName = class_getClassMethod(self, @selector(imageNamed:));
//交换方法地址,相当于交换实现方式
method_exchangeImplementations(imageWithName, imageName);
}
+ (instancetype)imageWithName:(NSString *)name
{
//这里调用imageWithName,相当于调用imageNamed
UIImage *image = [self imageWithName:name];
if (image == nil) {
image = [self imageWithName:@"1.jpg"];
// NSLog(@"加载空的图片");
}
return image;
}
//这里调用imageNamed方法实际上执行的是imageWithName方法,而在imageWithName里面又调用imageWithName方法实际上调用的是imageNamed的方法,也就是说两个方法的实现交换了
UIImage *image = [UIImage imageNamed:@"12"];
_imageView.image = image;