objective-c – 如何确定具有大量属性的对象(self)是否已更改?

简短版本的问题:
我有一个具有大量声明属性的类,我想跟踪是否有任何更改,所以当我调用save方法时,它不会写入数据库,当它是不需要如何更新isDirty属性而不为所有声明的属性编写自定义setter?

较长版本的问题:
假设我有一个这样的课程:

@interface MyObject : NSObject
{
@property (nonatomic, retain) NSString *myString;
@property (nonatomic, assign) BOOL     myBool;
// ... LOTS more properties
@property (nonatomic, assign) BOOL     isDirty;
}

...

@implementation MyObject
{
@synthesize myString;
@synthesize myBool;
// ... LOTS more synthesizes :)
@synthesize isDirty;
}

尝试1
我的第一个想法是实现setValue:forKey:像这样:

- (void)setValue:(id)value forKey:(NSString *)key {
    if (![key isEqualToString:@"isDirty"]) {
        if ([self valueForKey:key] != value) {
            if (![[self valueForKey:key] isEqual:value]) {
                self.isDirty = YES;
            }
        }
    }
    [super setValue:value forKey:key];
}

直到你直接用setter(即myObject.myString = @“new string”;)设置值,这样才能正常工作,在这种情况下setValue:forKey:不被调用(我不知道为什么我认为这将是, 大声笑)。

尝试2
观察自己的所有属性。

- (id)init
{
    // Normal init stuff
    // Start observing all properties of self
}

- (void)dealloc
{
    // Stop observing all properties of self
}

- (void)observeValueForKeyPath:(NSString *)keyPath 
                      ofObject:(id)object 
                        change:(NSDictionary *)change 
                       context:(void *)context
{
    // set isDirty to true
}  

我很确定这会奏效,但我认为必须有更好的方法。 🙂
我也希望这是自动的,所以我不必维护一个列表的属性来观看。我可以很容易的看到忘记在列表中添加一个属性,当它保持这个道路,然后试图找出为什么我的对象有时不能被保存。

希望我忽略了一个更简单的方法来解决这个问题!

最终解决方案
看下面我的答案我的最终解决方案。它是基于Josh Caswell提供的答案,但它是一个工作的例子。

这里有一点内省的帮助。 runtime functions可以为您提供所有对象属性的列表。然后,您可以使用这些来告诉KVO该列表中的脏是dependent。这避免了手动更新属性列表的可维护性问题。一个值得注意的是,像任何其他涉及KVO的解决方案一样,如果ivar直接更改,则不会收到通知 – 所有访问必须通过setter方法。

注册以在init中观察自己的脏键路径,并添加此方法,创建并返回一个NSSet,其中包含所有类的属性(当然是@“dirty”除外)的名称。

#import <objc/runtime.h>

+ (NSSet *)keyPathsForValuesAffectingDirty 
{
    unsigned int num_props;
    objc_property_t * prop_list;
    prop_list = class_copyPropertyList(self, &num_props);

    NSMutableSet * propSet = [NSMutableSet set];
    for( unsigned int i = 0; i < num_props; i++ ){
        NSString * propName = [NSString stringWithFormat:@"%s", property_getName(prop_list[i])];
        if( [propName isEqualToString:@"dirty"] ){
            continue;
        }
        [propSet addObject:propName];
    }
    free(prop_list);

    return propSet;
}

现在,只要设置了这个类的属性,就会触发脏的观察。 (请注意,超类中定义的属性不包括在该列表中。)

您可以使用该列表来单独注册为所有名称的观察者。

http://stackoverflow.com/questions/11398684/how-do-you-determine-if-an-object-self-with-a-lot-of-properties-has-been-chang

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:objective-c – 如何确定具有大量属性的对象(self)是否已更改?