我有一个要存储 CGRect 值的核心数据实体。因为没有对 Core Data 的 CGRect 支持,所以我只是将其拆分为四个浮点属性:x、y、宽度、高度。
为了让我更方便,我添加了一个自定义属性frame
,它从四个浮点属性返回组合的 CGRect。顺便说一句,我正在使用发电机。
@interface ViewableData : _ViewableData
@property (nonatomic) CGRect frame;
@end
@implementation ViewableData
- (void)setFrame:(CGRect)frame {
if (frame.origin.x != self.xValue)
self.xValue = frame.origin.x;
if (frame.origin.y != self.yValue)
self.yValue = frame.origin.y;
if (frame.size.width != self.widthValue)
self.widthValue = frame.size.width;
if (frame.size.height != self.heightValue)
self.heightValue = frame.size.height;
}
- (CGRect)frame {
return CGRectMake(self.xValue, self.yValue, self.widthValue, self.heightValue);
}
+ (NSSet *)keyPathsForValuesAffectingFrame {
return [NSSet setWithObjects:ViewableDataAttributes.height, ViewableDataAttributes.width, ViewableDataAttributes.x, ViewableDataAttributes.y, nil];
}
@end
它按我的预期工作,但我发现 KVO 观察者收到的通知次数超过了它需要的次数。设置一个框架可能会通知观察者 4 次。是不是要避免不必要的 KVO 更新通知?
编辑
看起来 Transformable 类型是一个很好的解决方案,但我仍然想知道更新依赖键路径的正确方法。另一个例子是拥有fullName
一个依赖于firstName
and的属性lastName
。不过,如果我改变fullName
了,我只希望观察者只收到一次通知而不是两次(一次firstName
更改,一次lastName
更改)。另一个问题是,在第一次通知时,状态不一致,因为只执行了部分更新。
我认为我原来的例子不够好。这个怎么样:
@interface Person : NSManagedObject
@property (copy, nonatomic) NSString fullName;
@property (copy, nonatomic) NSString firstName;
@property (copy, nonatomic) NSString lastName;
@end
@implementation Person
@dynamic firstName;
@dynamic lastName;
- (void)setFullName:(NSString *)fullName {
NSArray *names = [fullName componentsSeparatedByString:@" "];
self.firstName = names[0];
self.lastName = names[1];
}
- (CGRect)fullName {
return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName];
}
+ (NSSet *)keyPathsForValuesAffectingFrame {
return [NSSet setWithObjects:@"firstName", @"lastName", nil];
}
@end
那么如果我这样做
person = // get Person object
person.firstName = @"A";
person.lastName = @"B";
// person.fullName is now "A B"
person.fullName = @"C D";
在最后一行,观察者将看到拳头名称更新(全名“C B”,但这样的全名根本不存在,这可能会使我的应用程序崩溃)而不是姓氏更新(“C D”)