ZKReadStone
2017-08-08 18:37:45浏览 3673
1.为系统类添加属性
#import <UIKit/UIKit.h>
#import <objc/runtime.h>
@interface UIButton (Level)
@property (nonatomic, copy)NSString* level;
@end
import "UIButton+Level.h"
static NSString *key = @"key";///这里只是一个Key标示
@implementation UIButton (Level)
-(void)setLevel:(NSString *)level
{
objc_setAssociatedObject(self, &key,level, OBJC_ASSOCIATION_ASSIGN);
}
-(NSString *)level
{
return objc_getAssociatedObject(self, &key);
}
@end
////给Category添加属性
////先为扩展类声明需要添加的属性
///char runTime
/// objc_getAssociatedObject///设置getter
///objc_setAssociatedObject///设置setter
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.level = @"4级";
NSLog(@"================%@",btn.level);
2.更改成员变量的值
///动态的更改成员变量的值
- (void)changeInstanceVolume
{
//① 动态获取Car类中的所有属性[当然包括私有]
unsigned int count = 0;
Ivar *ivar = class_copyIvarList([self.car class], &count);
//②遍历属性找到对应name字段
for (int i = 0; i < count; i ++) {
Ivar var = ivar[i];
const char *varName = ivar_getName(var);
NSString *name = [NSString stringWithUTF8String:varName];
//③修改对应的字段值成age
if ([name isEqualToString:@"_name"]) {
object_setIvar(self.car, var, @"劳斯拉斯");
}
}
NSLog(@"%@",self.car.name);
}
3.字典转model
+ (instancetype)modelWithDict:(NSDictionary *)dict{
id model = [[self alloc] init];
unsigned int count = 0;
Ivar *ivars = class_copyIvarList(self, &count);
for (int i = 0 ; i < count; i++) {
Ivar ivar = ivars[i];
NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(ivar)];
//这里注意,拿到的成员变量名为_cid,_age
ivarName = [ivarName substringFromIndex:1];
id value = dict[ivarName];
[model setValue:value forKeyPath:ivarName];
}
return model;
}
4.消息转发相关
#import <Foundation/Foundation.h>
@interface Person : NSObject
- (void)run;
@end
#import "Person.h"
#include <objc/runtime.h>
#import "Car.h"
@implementation Person
///动态加载方法,当person对象调用run方法的时候,这时候重新写个方法添加里面
void runNew(id self, SEL cmd){
NSLog(@"================");
}
// 第一步,消息接收者没有找到对应的方法时候,会先调用此方法,可在此方法实现中动态添加新的方法
// 返回YES表示相应selector的实现已经被找到,或者添加新方法到了类中,否则返回NO
+ (BOOL)resolveInstanceMethod:(SEL)sel {
// if (sel == @selector(run)) {
// class_addMethod(self, sel, (IMP)runNew, "v@:");
// return YES;
// }
// return [super resolveInstanceMethod:sel];
return YES;
}
// 第二步, 如果第一步的返回NO或者直接返回了YES而没有添加方法,该方法被调用
// 在这个方法中,我们可以指定一个可以返回一个可以响应该方法的对象, 注意如果返回self就会死循环,这里返回的对象就是要转移寻找的列表,换成到Car类里面寻找run方法的实现
- (id)forwardingTargetForSelector:(SEL)aSelector {
// Car *car = [[Car alloc]init];
// return car;
return nil;
}
// 第三步, 如果forwardingTargetForSelector:返回了nil,则该方法会被调用,系统会询问我们要一个合法的『类型编码(Type Encoding)』也就是方法签名
// 若返回 nil,则不会进入下一步,而是无法处理消息
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
return [NSMethodSignature signatureWithObjCTypes:"v@:"];
// return nil;
}
// 当实现了此方法后,-doesNotRecognizeSelector: 将不会被调用
// 在这里进行消息转发
- (void)forwardInvocation:(NSInvocation *)anInvocation {
// 在这里可以改变方法选择器
[anInvocation setSelector:@selector(unknown)];
// 改变方法选择器后,需要指定消息的接收者
[anInvocation invokeWithTarget:self];
}
- (void)unknown {
NSLog(@"unkown method.......");
}
// 如果没有实现消息转发 forwardInvocation 则调用此方法
- (void)doesNotRecognizeSelector:(SEL)aSelector {
// NSLog(@"unresolved method :%@", NSStringFromSelector(aSelector));
}
@end