【发布时间】:2012-07-09 01:34:56
【问题描述】:
问题的简短版本:
我有一个带有大量声明属性的类,我想跟踪它是否有任何更改,以便当我在其上调用 save 方法时,它不会写入数据库它不是必需的。如何更新isDirty 属性无需为所有声明的属性编写自定义设置器?
问题的较长版本:
假设我有一个这样的课程:
@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
观察 self 的所有属性。
- (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
}
我很确定这会奏效,但我认为一定有更好的方法。 :) 我还希望这是自动的,这样我就不必维护要查看的属性列表。我很容易看到在维护它时忘记将属性添加到列表中,然后试图找出为什么我的对象 sometimes 没有得到保存。
希望我忽略了一个更简单的方法来解决这个问题!
最终解决方案
请参阅下面的答案,了解我对此的最终解决方案。它基于 Josh Caswell 提供的答案,但只是一个工作示例。
【问题讨论】:
-
不得不承认,我能想到的只有两种方法,一种是使用自定义 setter 方法,另一种是在写入文件,并将计算的 HASH 与存储在磁盘上的文件本身的 HASH 进行比较。好问题!
-
是的,我考虑过散列,但由于您可以使用两个不相同的对象拥有相同的散列,因此在需要保存对象时可能会不保存该对象。诚然,这可能不会经常发生,但这会让它更难追踪!
-
实际上这不应该是正确的(好的)哈希算法。一个好的 HASH 算法应该有很少的冲突。在只有 1 个输入位发生变化的情况下,良好的 HASH 算法将更改约 50% 的消息摘要位,并且还会考虑输入的顺序(即,如果在第 1 次运行时 a 在 b 之前通过,那么在第 2 次run b 在 a 之前通过,即使 a 和 be 没有改变,输出摘要也会不同)。
-
是的,我明白了,但您回复的关键是“很少”冲突......
-
我不认为你会担心的是我输入的内容。 MD5 校验和和 HASH 与 Internet 上的许多文件一起出现是有原因的!这也是它们被用作许多数字签名算法的输入的原因。
标签: objective-c ios observer-pattern