gpt4 book ai didi

objective-c - 您如何确定具有很多属性的对象(self)是否已被更改?

转载 作者:IT王子 更新时间:2023-10-29 08:16:15 25 4
gpt4 key购买 nike

问题的简短版本:
我有一个包含大量已声明属性的类,我想跟踪它是否有任何更改,以便当我对其调用 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
观察 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
}

我很确定这会奏效,但我认为一定有更好的方法。 :)我还希望这是自动的,这样我就不必维护要查看的属性列表。我可以很容易地看到在维护此列表时忘记将属性添加到列表,然后试图弄清楚为什么我的对象有时没有被保存。

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

最终解决方案
请参阅下面的答案以了解我对此的最终解决方案。它基于 Josh Caswell 提供的答案,但它是一个工作示例。

最佳答案

一点内省(introspection)应该有助于解决这个问题。 runtime functions可以为您提供所有对象属性的列表。然后你可以使用它们来告诉 KVO dirtydependent在那个名单上。这避免了必须手动更新属性列表的可维护性问题。需要注意的是,与涉及 KVO 的任何其他解决方案一样,如果直接更改 ivar,您将不会收到通知——所有访问必须通过 setter 方法。

init中注册观察selfdirty键路径,并添加这个方法,创建并返回一个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;
}

现在,只要设置了此类的任何属性,就会触发对dirty 的观察。 (请注意,父类(super class)中定义的属性不包含在该列表中。)

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

关于objective-c - 您如何确定具有很多属性的对象(self)是否已被更改?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11398684/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com