1.归档和解档
- (void)encodeWithCoder:(NSCoder*)aCoder{
unsignedintoutCount =0;
Ivar*vars =class_copyIvarList([selfclass], &outCount);
for(inti =0; i < outCount; i ++) {
Ivarvar = vars[i];
constchar*name =ivar_getName(var);
NSString*key = [NSStringstringWithUTF8String:name];
//注意kvc的特性是,如果能找到key这个属性的setter方法,则调用setter方法
//如果找不到setter方法,则查找成员变量key或者成员变量_key,并且为其赋值
//所以这里不需要再另外处理成员变量名称的“_”前缀
idvalue = [selfvalueForKey:key];
[aCoderencodeObject:valueforKey:key];
}
free(vars);
}
- (nullableinstancetype)initWithCoder:(NSCoder*)aDecoder{
if(self= [superinit]) {
unsignedintoutCount =0;
Ivar*vars =class_copyIvarList([selfclass], &outCount);
for(inti =0; i < outCount; i ++) {
Ivarvar = vars[i];
constchar*name =ivar_getName(var);
NSString*key = [NSStringstringWithUTF8String:name];
idvalue = [aDecoderdecodeObjectForKey:key];
[selfsetValue:valueforKey:key];
}
free(vars);
}
returnself;
}
2.字典转模型 或者 模型转字典
//字典转模型
+(id)objectWithKeyValues:(NSDictionary*)aDictionary{
idobjc = [[selfalloc]init];
for(NSString*keyinaDictionary.allKeys) {
idvalue = aDictionary[key];
/*判断当前属性是不是Model*/
objc_property_tproperty =class_getProperty(self, key.UTF8String);
unsignedintoutCount =0;
objc_property_attribute_t*attributeList =property_copyAttributeList(property, &outCount);
objc_property_attribute_tattribute = attributeList[0];
NSString*typeString = [NSStringstringWithUTF8String:attribute.value];
if([typeStringisEqualToString:@"@\"TestModel\""]) {
value = [selfobjectWithKeyValues:value];
}
/**********************/
//生成setter方法,并用objc_msgSend调用
NSString*methodName = [NSStringstringWithFormat:@"set%@%@:",[keysubstringToIndex:1].uppercaseString,[keysubstringFromIndex:1]];
SELsetter =sel_registerName(methodName.UTF8String);
if([objcrespondsToSelector:setter]) {
((void(*) (id,SEL,id))objc_msgSend) (objc,setter,value);
}
free(attributeList);
}
returnobjc;
}
//模型转字典
-(NSDictionary*)keyValuesWithObject{
unsignedintoutCount =0;
objc_property_t*propertyList =class_copyPropertyList([selfclass], &outCount);
NSMutableDictionary*dict = [NSMutableDictionarydictionary];
for(inti =0; i < outCount; i ++) {
objc_property_tproperty = propertyList[i];
//生成getter方法,并用objc_msgSend调用
constchar*propertyName =property_getName(property);
SELgetter =sel_registerName(propertyName);
if([selfrespondsToSelector:getter]) {
idvalue = ((id(*) (id,SEL))objc_msgSend) (self,getter);
/*判断当前属性是不是Model*/
if([valueisKindOfClass:[selfclass]] && value) {
value = [valuekeyValuesWithObject];
}
/**********************/
if(value) {
NSString*key = [NSStringstringWithUTF8String:propertyName];
[dictsetObject:valueforKey:key];
}
}
}
free(propertyList);
returndict;
}
3.写分类 比如给原有的类 加个属性或者加个方法
#import
staticconstvoid*associatedKey ="associatedKey";
staticconstvoid*topassociatedKey ="topassociatedKey";
staticconstvoid*letfassociatedKey ="letassociatedKey";
staticconstvoid*BottleassociatedKey ="BottleassociatedKey";
staticconstvoid*rightassociatedKey ="rightassociatedKey";
@implementationUIButton (ClickBlock)
-(void)setedgeWithTop:(CGFloat)topFloat andletf:(CGFloat)letfFloat andBottle:(CGFloat)bottleFloat andright:(CGFloat)right{
objc_setAssociatedObject(self, &topassociatedKey, [NSNumbernumberWithFloat:topFloat],OBJC_ASSOCIATION_COPY_NONATOMIC);
objc_setAssociatedObject(self, &letfassociatedKey, [NSNumbernumberWithFloat:letfFloat],OBJC_ASSOCIATION_COPY_NONATOMIC);
objc_setAssociatedObject(self, &BottleassociatedKey, [NSNumbernumberWithFloat:bottleFloat],OBJC_ASSOCIATION_COPY_NONATOMIC);
objc_setAssociatedObject(self, &rightassociatedKey, [NSNumbernumberWithFloat:right],OBJC_ASSOCIATION_COPY_NONATOMIC);
}
-(CGRect)edgerect{
NSNumber*topNumber =objc_getAssociatedObject(self, &topassociatedKey);
NSNumber*leftNumber =objc_getAssociatedObject(self, &letfassociatedKey);
NSNumber*bottleNumber =objc_getAssociatedObject(self, &BottleassociatedKey);
NSNumber*rightNumber =objc_getAssociatedObject(self, &rightassociatedKey);
if(topNumber && leftNumber && bottleNumber && rightNumber) {
returnCGRectMake(self.bounds.origin.x- leftNumber.floatValue,self.bounds.origin.y- topNumber.floatValue,self.bounds.size.width+ leftNumber.floatValue+rightNumber.floatValue,self.bounds.size.height+ topNumber.floatValue+bottleNumber.floatValue);
}else{
returnself.bounds;
}
}
//Category中的属性,只会生成setter和getter方法,不会生成成员变量
-(void)setClick:(clickBlock)click{
objc_setAssociatedObject(self,associatedKey, click,OBJC_ASSOCIATION_COPY_NONATOMIC);
[selfremoveTarget:selfaction:@selector(buttonClick)forControlEvents:UIControlEventTouchUpInside];
if(click) {
[selfaddTarget:selfaction:@selector(buttonClick)forControlEvents:UIControlEventTouchUpInside];
}
}
-(UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event{
CGRectrect = [selfedgerect];
if(CGRectEqualToRect(rect,self.bounds)) {
return[superhitTest:pointwithEvent:event];
}else{
returnCGRectContainsPoint(rect, point)?self:nil;
}
}
-(clickBlock)click{
returnobjc_getAssociatedObject(self,associatedKey);
}
-(void)buttonClick{
if(self.click) {
self.click();
}
}
4.动态方法解析
-(void)jump{
NSLog(@"monkey can not fly, but! monkey can jump");
}
+(BOOL)resolveInstanceMethod:(SEL)sel{
/*
如果当前对象调用了一个不存在的方法
Runtime会调用resolveInstanceMethod:来进行动态方法解析
我们需要用class_addMethod函数完成向特定类添加特定方法实现的操作
返回NO,则进入下一步forwardingTargetForSelector:
*/
#if0
returnNO;
#else
class_addMethod(self, sel,class_getMethodImplementation(self,sel_registerName("jump")),"v@:");
return[superresolveInstanceMethod:sel];
#endif
}
-(id)forwardingTargetForSelector:(SEL)aSelector{
/*
在消息转发机制执行前,Runtime系统会再给我们一次重定向的机会
通过重载forwardingTargetForSelector:方法来替换消息的接受者为其他对象
返回nil则进步下一步forwardInvocation:
*/
#if0
returnnil;
#else
return[[Birdalloc]init];
#endif
}
-(NSMethodSignature*)methodSignatureForSelector:(SEL)aSelector{
/*
获取方法签名进入下一步,进行消息转发
*/
return[NSMethodSignaturesignatureWithObjCTypes:"v@:"];
}
-(void)forwardInvocation:(NSInvocation*)anInvocation{
/*
消息转发
*/
return[anInvocationinvokeWithTarget:[[Birdalloc]init]];
}