添加更新
RunTime消息机制:
- (void)viewDidLoad {
[superviewDidLoad];
Person*p = [[Personalloc]init];
[peat];
// OC:运行时机制,消息机制是运行时机制最重要的机制
//消息机制:任何方法调用,本质都是发送消息
// SEL:方法编号,根据方法编号就可以找到对应方法实现
[pperformSelector:@selector(eat)];
//让p发送消息
objc_msgSend(p,@selector(eat));
objc_msgSend(p,@selector(run:),10);
//类名调用类方法,本质类名转换成类对象
[Personeat];
//获取类对象
ClasspersonClass = [Personclass];
[personClassperformSelector:@selector(eat)];
//运行时
objc_msgSend(personClass,@selector(eat));
}
使用场景一:交换方法
例:用imageNamed加载图片的时候,并不知道图片是否加载成功
//如果自定义方法:
// 1.每次使用,都需要导入头文件
2.当一个项目开发太久,使用这个方式不靠谱
//所以只能扩展类方法:
imageNamed:
//实现方法:底层调用WC_imageNamed
//本质:交换两个方法的实现imageNamed和WC_imageNamed方法
//调用imageNamed其实就是调用WC_imageNamed
具体实现:
#import"UIImage+Image.h"
#import
@implementationUIImage (Image)
// 加载这个分类的时候调用
+ (void)load
{
//交换方法实现,方法都是定义在类里面
//class_getMethodImplementation:获取方法实现
//class_getInstanceMethod:获取对象
//class_getClassMethod:获取类方法
//IMP:方法实现
//imageNamed
//Class:获取哪个类方法
//SEL:获取方法编号,根据SEL就能去对应的类找方法
MethodimageNameMethod =class_getClassMethod([UIImageclass],@selector(imageNamed:));
//WC_imageNamed
MethodWC_imageNamedMethod =class_getClassMethod([UIImageclass],@selector(WC_imageNamed:));
//交换方法实现
method_exchangeImplementations(imageNameMethod,
WC_imageNamedMethod);
}
//运行时
//先写一个其他方法,实现这个功能
//在分类里面不能调用super,分类木有父类,如:
//+(UIImage *)imageNamed:(NSString *)name
//{
//[super imageNamed]
//}
+ (UIImage*)WC_imageNamed:(NSString*)imageName
{
//1.加载图片
UIImage*image = [UIImageWC_imageNamed:imageName];
//2.判断功能
if(image ==nil){
NSLog(@"加载image为空");
}
returnimage;
}
使用场景二:动态添加方法
例:没有在@interface声明方法的情况下动态添加方法
具体实现:
#import"Person.h"
#import
@implementation Person
//默认一个方法都有两个参数,self,_cmd,隐式参数
// self:方法调用者
// _cmd:调用方法的编号
//动态添加方法,首先实现这个resolveInstanceMethod
// resolveInstanceMethod调用:当调用了没有实现的方法没有实现就会调用resolveInstanceMethod
// resolveInstanceMethod作用:就知道哪些方法没有实现,从而动态添加方法
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
//NSLog(@"%@",NSStringFromSelector(sel));
//动态添加eat方法
if(sel ==@selector(eat:)){
/*
cls:给哪个类添加方法
SEL:添加方法的方法编号是什么
IMP:方法实现,函数入口,函数名
types:方法类型
*/
// @:对象:SEL
class_addMethod(self, sel, (IMP)aaaa,"v@:@");
//处理完
returnYES;
}
return[superresolveInstanceMethod:sel];
}
//定义函数
//没有返回值,参数(id,SEL)
//void(id,SEL)
voidaaaa(idself,SEL_cmd,idparam1)
{
NSLog(@"调用eat %@ %@
%@",self,NSStringFromSelector(_cmd),param1);
}
@end
适用场景三:给分类添加属性
例:在分类的@interface中没有声明属性的情况下,动态的添加属性
适用场景四:字典转模型
例:跟KVC一样的字典转模型功能
具体实现:
//NSObject+Model.m
#import"NSObject+Model.h"
#import
/*
Ivar ivar1;
Ivar ivar2;
Ivar ivar3;
Ivar a[] = {ivar3,ivar1,ivar2};
Ivar *ivar = &a;
*/
@implementationNSObject (Model)
+ (instancetype)modelWithDict:(NSDictionary*)dict{
//创建对应类的对象
idobjc = [[selfalloc]init];
//runtime:遍历模型中所有成员属性,去字典中查找
//属性定义在哪,定义在类,类里面有个属性列表(数组)
//遍历模型所有成员属性
//ivar:成员属性
//class_copyIvarList:把成员属性列表复制一份给你
//Ivar *:指向Ivar指针
//Ivar *:指向一个成员变量数组
//class:获取哪个类的成员属性列表
//count:成员属性总数
unsignedintcount =0;
Ivar*ivarList =class_copyIvarList(self, &count);
for(inti =0; i < count; i++) {
//获取成员属性
Ivarivar = ivarList[i];
//获取成员名
NSString*propertyName = [NSStringstringWithUTF8String:ivar_getName(ivar)];
//成员属性类型
NSString*propertyType = [NSStringstringWithUTF8String:ivar_getTypeEncoding(ivar)];
//获取key
NSString*key = [propertyNamesubstringFromIndex:1];
//获取字典的value
idvalue = dict[key];
//给模型的属性赋值
// value:字典的值
// key:属性名
if(value) {
//KVC赋值:不能传空
[objcsetValue:valueforKey:key];
}
//NSLog(@"%@",key);
//NSLog(@"%@ %@",propertyType , propertyName);
}
returnobjc;
}
@end