来自:http://www.imlifengfeng.com/blog/?p=397 1、快速归档
-
(id)initWithCoder:(NSCoder *)aDecoder { if (self = [super init]) { unsigned int outCount; Ivar * ivars = class_copyIvarList([self class], &outCount); for (int i = 0; i < outCount; i ++) { Ivar ivar = ivars[i]; NSString * key = [NSString stringWithUTF8String:ivar_getName(ivar)]; [self setValue:[aDecoder decodeObjectForKey:key] forKey:key]; } } return self; }
-
(void)encodeWithCoder:(NSCoder *)aCoder { unsigned int outCount; Ivar * ivars = class_copyIvarList([self class], &outCount); for (int i = 0; i < outCount; i ++) { Ivar ivar = ivars[i]; NSString * key = [NSString stringWithUTF8String:ivar_getName(ivar)]; [aCoder encodeObject:[self valueForKey:key] forKey:key]; } }
2、Json到Model的转化
-
(instancetype)initWithDict:(NSDictionary *)dict {
if (self = [self init]) { //(1)获取类的属性及属性对应的类型 NSMutableArray * keys = [NSMutableArray array]; NSMutableArray * attributes = [NSMutableArray array]; /* * 例子 * name = value3 attribute = T@"NSString",C,N,V_value3 * name = value4 attribute = T^i,N,V_value4 */ unsigned int outCount; objc_property_t * properties = class_copyPropertyList([self class], &outCount); for (int i = 0; i < outCount; i ++) { objc_property_t property = properties[i]; //通过property_getName函数获得属性的名字 NSString * propertyName = [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding]; [keys addObject:propertyName]; //通过property_getAttributes函数可以获得属性的名字和@encode编码 NSString * propertyAttribute = [NSString stringWithCString:property_getAttributes(property) encoding:NSUTF8StringEncoding]; [attributes addObject:propertyAttribute]; } //立即释放properties指向的内存 free(properties);
//(2)根据类型给属性赋值for (NSString * key in keys) {if ([dict valueForKey:key] == nil) continue;[self setValue:[dict valueForKey:key] forKey:key];} 复制代码
} return self; }
3、Category添加属性并生成getter和setter方法 #import <Foundation/Foundation.h>
@interface NSArray (MyCategory) //不会生成添加属性的getter和setter方法,必须我们手动生成 @property (nonatomic, copy) NSString *blog; @end
#import "NSArray+MyCategory.h" #import <objc/runtime.h>
@implementation NSArray (MyCategory)
// 定义关联的key static const char *key = "blog";
/** blog的getter方法 */
- (NSString *)blog { // 根据关联的key,获取关联的值。 return objc_getAssociatedObject(self, key); }
/** blog的setter方法 */
- (void)setBlog:(NSString *)blog { // 第一个参数:给哪个对象添加关联 // 第二个参数:关联的key,通过这个key获取 // 第三个参数:关联的value // 第四个参数:关联的策略 objc_setAssociatedObject(self, key, blog, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } @end
4、Method Swizzling使用 #import "UIViewController+swizzling.h" #import <objc/runtime.h> @implementation UIViewController (swizzling)
- (void)load { // 通过class_getInstanceMethod()函数从当前对象中的method list获取method结构体,如果是类方法就使用class_getClassMethod()函数获取。 Method fromMethod = class_getInstanceMethod([self class], @selector(viewDidLoad)); Method toMethod = class_getInstanceMethod([self class], @selector(swizzlingViewDidLoad)); /**
- 我们在这里使用class_addMethod()函数对Method Swizzling做了一层验证,如果self没有实现被交换的方法,会导致失败。
- 而且self没有交换的方法实现,但是父类有这个方法,这样就会调用父类的方法,结果就不是我们想要的结果了。
- 所以我们在这里通过class_addMethod()的验证,如果self实现了这个方法,class_addMethod()函数将会返回NO,我们就可以对其进行交换了。 */ if (!class_addMethod([self class], @selector(swizzlingViewDidLoad), method_getImplementation(toMethod), method_getTypeEncoding(toMethod))) { method_exchangeImplementations(fromMethod, toMethod); } }
// 我们自己实现的方法,也就是和self的viewDidLoad方法进行交换的方法。
- (void)swizzlingViewDidLoad { NSString *str = [NSString stringWithFormat:@"%@", self.class]; // 我们在这里加一个判断,将系统的UIViewController的对象剔除掉 if(![str containsString:@"UI"]){ NSLog(@"统计打点 : %@", self.class); } [self swizzlingViewDidLoad]; } @end
5、Method Swizzling类簇 __NSArrayI才是NSArray真正的类 #import "NSArray+ MyArray.h" #import "objc/runtime.h" @implementation NSArray MyArray)
- (void)load {//是加载文件到内存执行的方法 跟类的生命周期没有关系 Method fromMethod = class_getInstanceMethod(objc_getClass("__NSArrayI"), @selector(objectAtIndex:)); Method toMethod = class_getInstanceMethod(objc_getClass("__NSArrayI"), @selector(my_objectAtIndex:)); method_exchangeImplementations(fromMethod, toMethod); }
- (id)my_objectAtIndex:(NSUInteger)index { if (self.count-1 < index) { // 这里做一下异常处理,不然都不知道出错了。 @try { return [self my_objectAtIndex:index]; } @catch (NSException *exception) { // 在崩溃后会打印崩溃信息,方便我们调试。 NSLog(@"---------- %s Crash Because Method %s ----------\n", class_getName(self.class), func); NSLog(@"%@", [exception callStackSymbols]); return nil; } @finally {} } else { return [self my_objectAtIndex:index]; } } @end