2013-12-18 100 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