OC方法的本质:
Runtime技术的使用基于OC是一门动态语言,那么何为动态语言呢?动态语言意味着变量类型的确认以及方法的实现由编译期推后到了运行期(这也就是为什么我们运行iOS APP有时会报错unrecognized selector错误)。
runtime常用的技术点:
- 方法交换
- 方法添加
- 操作属性
// 消息机制
Person *p = objc_msgSend([Person class], @selector(alloc));
p = objc_msgSend(p, @selector(init));
objc_msgSend(p, @selector(run:),20);
// 交换方法
+ (void)load{
Method imageNamed = class_getClassMethod(self, @selector(imageNamed:));
Method lsw_imageNamed = class_getClassMethod(self, @selector(lsw_imageNamed:));
method_exchangeImplementations(imageNamed, lsw_imageNamed);
}
+ (UIImage *)lsw_imageNamed:(NSString *)name{
UIImage *image = [UIImage lsw_imageNamed:name];
if (image == nil) {
NSLog(@"无法加载图片");
}
return image;
}
// 动态添加方法
// 什么时候调用:只要调用没有实现的方法 就会调用方法去解决
// 作用:去解决没有实现方法,动态添加方法
+ (BOOL)resolveInstanceMethod:(SEL)sel{
/*
class:目标类
SEL:方法编号
IMP:方法实现
type:方法类型
*/
// [NSStringFromSelector(sel) isEqualToString:@"eat"];
if (sel == @selector(run:)) {
// 添加方法
class_addMethod(self, sel, (IMP)run, nil);
return YES;
}
return [super resolveInstanceMethod:sel];
}
// 动态调用方法
[p performSelector:@selector(run:) withObject:@20];
// 自定义对象归档应用
- (void)encodeWithCoder:(NSCoder *)aCoder{
unsigned int count = 0;
Ivar *ivarList = class_copyIvarList(Person.class, &count);
for (int i=0; i<count; i++) {
Ivar ivar = ivarList[i];
NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];
[aCoder encodeObject:[self valueForKey:key] forKey:key];
}
free(ivarList);
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder{
self = [super init];
if (self) {
unsigned int count = 0;
Ivar *ivarList = class_copyIvarList(Person.class, &count);
for (int i=0; i<count; i++) {
Ivar ivar = ivarList[i];
NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];
id value = [aDecoder decodeObjectForKey:key];
[self setValue:value forKey:key];
}
free(ivarList);
}
return self;
}
// 动态添加带有参数的方法
// self和_cmd是两个隐藏的参数
void eat(id self,SEL _cmd,id objc){
NSLog(@"在这里吃了:%@",objc);
}
网友评论