runtime小结黑魔法
(一)拦截交换系统设置图片的方法
#import <UIKit/UIKit.h> @interface UIImage (MyImage) + (UIImage *)theNewImageName:(NSString *)name; @end
#import "UIImage+MyImage.h" #import <objc/runtime.h> @implementation UIImage (MyImage) + (void)load { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ //交换设置图片的方法 #pragma mark ---如果需要交换的方法是 “-”实例方法 就用 class_getInstanceMethod, ,如果是“+”类方法 就用class_getClassMethod Method originMethod = class_getClassMethod(self, @selector(imageNamed:)); Method customMethod = class_getClassMethod(self, @selector(theNewImageName:)); method_exchangeImplementations(originMethod, customMethod); }); } + (UIImage *)theNewImageName:(NSString *)name { NSString *theName = [NSString stringWithFormat:@"new_%@",name]; return [UIImage theNewImageName:theName]; } @end
(二)给系统类添加属性
#import <Foundation/Foundation.h> @interface NSDictionary (MyDictionary) //给字典类增加属性 @property (nonatomic, copy) NSString *name; @property (nonatomic, copy) NSString *gender; @end
#import "NSDictionary+MyDictionary.h" #import <objc/runtime.h> @implementation NSDictionary (MyDictionary) /** 在延展里面都 * object:要关联的对象 key:要关联的属性的key值 value:要关联的属性 polocy:是枚举类型 enum { OBJC_ASSOCIATION_ASSIGN = 0, 所修饰的属性对象是弱引用的 OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, 强引用,非线程安全 OBJC_ASSOCIATION_COPY_NONATOMIC = 3, 指定相关的复制对象,非线程安全 OBJC_ASSOCIATION_RETAIN = 01401, 指定关联的对象的强引用,线程安全 默认atomic OBJC_ASSOCIATION_COPY = 01403 指定相关的复制对象 ,默认是atomic }; */ - (void)setName:(NSString *)name { objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_COPY_NONATOMIC); } - (NSString *)name { return objc_getAssociatedObject(self, @selector(name)); } - (void)setGender:(NSString *)gender { objc_setAssociatedObject(self, @selector(gender), gender, OBJC_ASSOCIATION_COPY_NONATOMIC); } - (NSString *)gender { return objc_getAssociatedObject(self, @selector(gender)); } @end
(三)使用RunTime给类属性归档
#import <Foundation/Foundation.h> @interface Person : NSObject - (void)eat; - (void)drink; @property (nonatomic, copy) NSString *name; @property (nonatomic, copy) NSString *gender; @property (nonatomic, assign) NSInteger age; @end
//归档 - (void)encodeWithCoder:(NSCoder *)aCoder { unsigned int count = 0; //1.获得变量列表数组 Ivar *ivarList = class_copyIvarList([self class], &count); //2.循环 for (int i = 0; i < count; i++) { //3.获取变量名 Ivar ivar = ivarList[i]; //4.将c语言字符串转换成 oc字符串 NSString *ivarString = [NSString stringWithUTF8String:ivar_getName(ivar)]; //5.归档 [aCoder encodeObject:[self valueForKey:ivarString] forKey:ivarString]; } } //反归档 - (instancetype)initWithCoder:(NSCoder *)aDecoder { self = [super init]; if (self) { unsigned int count = 0; Ivar *ivarList = class_copyIvarList([self class], &count); for (int i = 0; i < count; i++) { Ivar ivar = ivarList[i]; NSString *ivarString = [NSString stringWithUTF8String:ivar_getName(ivar)]; //反归档 [self setValue:[aDecoder decodeObjectForKey:ivarString] forKey:ivarString]; } } return self; }