CGRect値を保存したいCoreDataエンティティがあります。Core DataにはCGRectがサポートされていないため、x、y、width、heightの4つのfloat属性に分割しました。
私にとってより便利にするためにframe
、4つのfloat属性から結合されたCGRectを返すカスタムプロパティを追加します。ところで、私はmogeneratorを使用しています。
@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更新通知を回避するのですか?
編集
変形可能なタイプは良い解決策ですが、依存キーパスを更新する適切な方法を知りたいです。もう1つの例は、とfullName
に依存するプロパティを持つことです。それでも、変更した場合、オブザーバーには2回ではなく1回だけ通知されると思います(1回は変更され、もう1回は変更されます)。もう1つの問題は、最初の通知では、部分的にしか更新が実行されないため、状態に一貫性がないことです。firstName
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 D")よりも更新された最初の名前( "C B"のフルネームで、しかしそのようなフルネームはまったく存在しないため、アプリがクラッシュする可能性があります)が表示されます。