runtime的运用: (以下代码全部都基于Dog类创建的一个对象:dog)
1.使用id类型来创建变量以便接受不同类型的对象
2.使用 [person performSelector:@selector(test2:) withObject:@"传入参数"];来动态的调用方法;
3.使用objc_setAssociatedObject(id object,const void *key,id value,objc_AssociationPolicy policy)为对象object添加额外的存储空间.
4.动态copy对象
在MRC模式下使用:
Dog *dog = [Dognew];
dog.name = @"1234";
dog.age = 3;
Dog *copyDog = object_copy(dog,sizeof(dog));
5.动态设置对象的归属类object_setClass 或者获得对象的归属类
object_setClass如下列代码:
Dog *dog = [Dognew];
NSLog(@"dog.class==%@",[dogclass]);
NSLog(@"%@",object_setClass(dog, [Catclass])); //Object_setClass的返回值为对象原来的所属类
NSLog(@"dog.class==%@",[dogclass]);
将输出:
dog.class==Dog
Dog
dog.class==Cat
object_getClass 如下代码:
Dog *dog = [Dognew];
Class class = object_getClass(dog);
NSLog(@"%@",class);
将输出:Dog
也就是动态的获得dog对象的所属类
5.respondsToSelector 以及 performSelector
respondsToSelector,用来判断对象是否可以调用对应的方法,传入一个SEL类型的值
performSelector用来直接使用对象调用方法,传入一个SEL类型的参数,经常将两者结合来用,示例如下:
if ([dog respondsToSelector:@selector(funOfDog)]) {
[dog performSelector:@selector(funOfDog)];
}else if([dogrespondsToSelector:@selector(funOfCat)]){
[dog performSelector:@selector(funOfCat)];
}
判断dog类可以相应那种方法并且直接调用它.
6.使用object_getClassName获取类名,只不过是C+字符串的格式
const char * className =object_getClassName(dog);
printf("%s",className);
输出:Dog
7.为对象添加方法
为Dog类添加私有方法,因为这个方法是动态添加的,所以只能使用使用respondsToSelector来动态的调用这个方法,否则的话,编译是不通过的,因为在被添加的类中,该方法即没有实现也没有声明.
class_addMethod([Dogclass], @selector(dogAddFun:str2:), (IMP)funOfAdd,"[email protected]:@@");
if ([dog respondsToSelector:@selector(dogAddFun:str2:)]) {
int number = [dogperformSelector:@selector(dogAddFun:str2:)withObject:@"1234"withObject:@"5678"];
NSLog(@"%d",number);
}else
NSLog(@"方法没有添加成功");
funOfAdd方法定义:
int funOfAdd(idself,SEL_cmd,NSString *str,NSString* str2){
return (int)(str.length + str2.length);
} //返回两个字符串长度相加的和
8.获取一个类的所有方法 class_copyMethodList
u_int count;
Method *methods = class_copyMethodList([dog class], &count);
for (int i = 0 ; i < count; i ++){
SEL name = method_getName(methods[i]);
printf("%s\n",sel_getName(name));
}
其中,class_copyMethodList的两个参数分别为类名和统计方法数量的无符号整形的变量地址,其返回值为一个包含该类所有objc_method方法的数组
method_getName传入的参数是该类中的objc_method对象,返回值为该方法对应的SEL,其在runtime源码中的实现如下:
SEL method_getName(Method m)
{
if (!m) return NULL;
return oldmethod(m)->method_name;
}
sel_getName(name)则是通过SEL获取该SEL对应的方法名
9.获取一个类的所有属性名
u_int count;
objc_property_t* properites = class_copyPropertyList([dog class], &count);
for(int i = 0 ; i < count;i ++){
const char* name= property_getName(properites[i]);
printf("%s\n",name);
}
class_copyPropertyList返回一个包含该类所有属性的数组,property_getName获得该objc_property_t对应的属性名 的字符串.
10.系统类方法的替换
可以互换两个方法的实现 ,但是没感觉有什么用途 ,估计是没遇到有次需求的问题
Method method1 = class_getInstanceMethod([NSString class],@selector(lowercaseString));
Method method2 = class_getInstanceMethod([NSString class],@selector(uppercaseString));
method_exchangeImplementations(method1, method2);
NSLog(@"%@",[@"aaaaaa" lowercaseString]);
NSLog(@"%@",[@"BBBBB" uppercaseString]);
11.实现自定义方法的替换
Method method1 = class_getInstanceMethod([dog class],@selector(funOfDog));
Method funMethod = class_getInstanceMethod([self class],@selector(replaseFun));
IMP imp = method_getImplementation(funMethod);
method_setImplementation(method1, imp);
[dog funOfDog];
funOfDog是dog类里定义的方法,replaseFun是在调用控制器里定义的方法,两个方法都只有一条输出语句,执行完上述语句后,dog调用funOfDog执行的是在本控制器里输出的语句.