2013-12-18 59 views
4

我想覆盖setter和getter并找到objc_property_t的类,而不是单独为每个属性执行此操作。覆盖子类的所有设置者和获取者

我得到像这样所有的属性:

unsigned int numberOfProperties; 
    objc_property_t *propertyArray = class_copyPropertyList([self class], &numberOfProperties); 
    for (NSUInteger i = 0; i < numberOfProperties; i++) { 
     objc_property_t property = propertyArray[i]; 
     NSString *name = [[NSString alloc] initWithUTF8String:property_getName(property)]; 

     property.getter = SEL; //? 
    } 

这是我怎么想覆盖getter和setter一个例子 - 如果有一个更好的办法,让我知道。 NSInvocation也许?

- (UIImage *)backgroundImage 
{ 
    return [self overrideGetterWithSelector:NSStringFromSelector(_cmd)]; 
} 

- (void)setBackgroundImage:(UIImage *)backgroundImage 
{ 
    [self overrideSetterForObject:backgroundImage forSelector:NSStringFromSelector(_cmd)]; 
} 

或者有没有办法拦截所有发送到类的消息?

我的目标是制定一种通用的方法来存储启动之间的类的属性。您可能想问为什么我不使用NSUserDefaultsNSKeyedArchiver。那么,我正在使用NSKeyedArchiver - 我不想手动覆盖每一个setter和getter。

+0

为什么不使用CoreData? – hypercrypt

+0

1.核心数据真的是矫枉过正,我想做的事 - 设置和获取属性。 2.我想创建一个可重用的课程,只需要很少的工作就可以完成设置。只需添加一个属性即可。 – Kevin

回答

5

您可以使用objc运行时的class_replaceMethod替换getter的实现。

例子:

- (void)replaceGetters { 
    unsigned int numberOfProperties; 
    objc_property_t *propertyArray = class_copyPropertyList([self class], &numberOfProperties); 
    for (NSUInteger i = 0; i < numberOfProperties; i++) { 
     objc_property_t property = propertyArray[i]; 
     const char *attrs = property_getAttributes(property); 
     NSString *name = [[NSString alloc] initWithUTF8String:property_getName(property)]; 

     // property.getter = SEL; //? 
     // becomes 
     class_replaceMethod([self class], NSSelectorFromString(name), (IMP)myNewGetter, attrs); 
    } 
} 

id myNewGetter(id self, SEL _cmd) { 
    // do whatever you want with the variables.... 

    // you can work out the name of the variable using - NSStringFromSelector(_cmd) 
    // or by looking at the attributes of the property with property_getAttributes(property); 
    // There's a V_varName in the property attributes 
    // and get it's value using - class_getInstanceVariable() 
    //  Ivar ivar = class_getInstanceVariable([SomeClass class], "_myVarName"); 
    //  return object_getIvar(self, ivar); 
} 
+0

这正是我正在寻找的,谢谢。 – Kevin

2

您可以在此设置KVO并保存更改的数据。

static const void *KVOContext = &KVOContext; 

unsigned int numberOfProperties; 
objc_property_t *propertyArray = class_copyPropertyList([self class], &numberOfProperties); 
for (NSUInteger i = 0; i < numberOfProperties; i++) 
{ 
    objc_property_t property = propertyArray[i]; 
    NSString *name = [[NSString alloc] initWithUTF8String:property_getName(property)]; 
    [self addObserver:self forKeyPath:name options:kNilOptions context:KVOContext]; 
} 
+0

我在这里看到了这个方法http://stackoverflow.com/questions/3374132/using-one-setter-for-all-model-ivars?rq=1,但是我想重写getter,这样我就可以懒洋洋地实例化值。我会做更多的体验,谢谢。 – Kevin