1.归档与反归档
#import
#import
#import "Dog.h"
@interface Person : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *gender;
@property (nonatomic, strong) NSNumber *age;
@property (nonatomic, assign) NSInteger weight;
@property (nonatomic, strong) Dog *dog;
+ (Person *)personWithName:(NSString *)name gender:(NSString *)gender age:(NSNumber *)age weight:(NSInteger)weight;
- (void)getPersonMessage;
- (void)walkonTheStreet:(NSString *)str;
@end
#import "Person.h"
#import // 导入
@interface Person ()
@end
@implementation Person
- (void)encodeWithCoder:(NSCoder *)aCoder
{
unsigned int outCount;
Ivar *ivarList = class_copyIvarList([Person class], &outCount);
for (NSInteger i = 0; i < outCount; i++) { // 采用for循环遍历属性,无需一一归档
const char *cName = ivar_getName(ivarList[i]);
NSString *name = [NSString stringWithUTF8String:cName];
[aCoder encodeObject:[self valueForKey:name] forKey:name];
}
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self) {
unsigned int outCount;
Ivar *ivarList = class_copyIvarList([Person class], &outCount);
for (NSInteger i = 0; i < outCount; i++) { // 采用for循环遍历属性,无需一一反归档
const char *cName = ivar_getName(ivarList[i]);
NSString *name = [NSString stringWithUTF8String:cName];
[self setValue:[aDecoder decodeObjectForKey:name] forKey:name];
}
}
return self;
}
如下方法
Ivar *class_copyIvarList(Class cls, unsigned int *outCount) //获取所有成员变量
const char *ivar_getName(Ivar v) //获取某个成员变量的名字
const char *ivar_getTypeEncoding(Ivar v) //获取某个成员变量的类型编码
Ivar class_getInstanceVariable(Class cls, const char *name) //获取某个类中指定名称的成员变量
id object_getIvar(id obj, Ivar ivar) //获取某个对象中的某个成员变量的值
void object_setIvar(id obj, Ivar ivar, id value) //设置某个对象的某个成员变量的值
TypeEncoding:https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html#//apple_ref/doc/uid/TP40008048-CH100-SW1 // 编码形式
打印实例变量
- (NSString *)description
{
/*
* class: 要获取的某个类, outCount: 通过这一个函数执行之后会将成员变量的个数赋值到此
*/
unsigned int outCount;
Ivar *ivarList = class_copyIvarList([Person class], &outCount);
for (NSInteger i = 0; i < outCount; i ++) {
// 每次获取一个成员变量
Ivar ivar = ivarList[i];
// 打印成员变量的名字和类型编码
NSLog(@"name = %s, type = %s",ivar_getName(ivar), ivar_getTypeEncoding(ivar));
}
return nil;
}
2.消息转发
OC的消息发送机制根据方法名来寻找声明完成的实例方法的实现方法,当类中的方法只声明而未实现时,系统会在逐级父类中寻找方法的实现,当父类中均无方法的实现时, 系统会执行以下方法,故可为未实行的方法进行消息转发,添加实现
1 + resolveInstanceMethod:(SEL)sel // 为一个实例方法动态添加实现
+ resolveClassMethod:(SEL)sel // 为一个类方法动态添加实现
2 - (id)forwardingTargetForSelector:(SEL)aSelector
//为没有实现的方法指定一个对象
3 - (void)forwardInvocation:(NSInvocation *)anInvocation
//子类重载这个方法为消息指定其他对象
a. 为一个实例方法动态添加实现
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
// 将方法转换为字符串
NSString *selString = NSStringFromSelector(sel);
if ([selString isEqualToString:@"walkonTheStreet:"]) {
// 为一个没有实现的方法动态添加实现
/* cls: 类
name: 没有实现的方法
IMP: 要添加的实现
types: 动态添加的实现的类型编码*/
class_addMethod(self, @selector(walkonTheStreet:), (IMP)walkFunc, "V@:@"); // void的编码为 V, SEL的编码为 :
}
return [super resolveInstanceMethod:sel];
}
void walkFunc(id self,SEL sel, NSString *str){
NSLog(@"Person---%s------%@", __func__, str);
}
b. 为没有实现的方法指定一个对象
方式1
- (id)forwardingTargetForSelector:(SEL)aSelector
{
NSString *selString = NSStringFromSelector(aSelector);
if ([selString isEqualToString:@"walkonTheStreet:"]) {
self.dog = [Dog new];
return self.dog;
}
return [super forwardingTargetForSelector:aSelector];
}
方式2
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
if ([Dog instanceMethodSignatureForSelector:anInvocation.selector]) {
self.dog = [Dog new];
[anInvocation invokeWithTarget:self.dog];
}
}
// 给方法制定一个有效的签名
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
NSMethodSignature *methodSignature = [super methodSignatureForSelector:aSelector];
if (!methodSignature) {
methodSignature = [Dog instanceMethodSignatureForSelector:aSelector];
}
return methodSignature;
}
3.给类目添加实例变量
延展可为类添加属性和方法, 但外界不可访问; 类目可为类添加方法,但无法添加实例变量, 采用runtime可为类目添加外界可访问的实例变量
#import
@interface NSDictionary (Mydict)
@property (nonatomic,strong) NSString *name;
@end
#import "NSDictionary+Mydict.h"
#import
@implementation NSDictionary (Mydict)
/*
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy) //为某个类关联某个对象
id objc_getAssociatedObject(id object, const void *key)
//获取到某个类的某个关联对象
void objc_removeAssociatedObjects(id object) //移除已经关联的对象
*/
// 关联后此属性name在外界可以访问,并且通过移除对象方法随时移除
- (void)setName:(NSString *)name
{
// objc: 要关联的对象 key: 成员变量对应的key值
// @selector(属性名) value: value
objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_COPY_NONATOMIC); // set方法
}
- (NSString *)name
{
return objc_getAssociatedObject(self, @selector(name)); //get方法
}