为啥我的 ivar 没有在 NSManagedObject 子类上设置
Posted
技术标签:
【中文标题】为啥我的 ivar 没有在 NSManagedObject 子类上设置【英文标题】:Why is my ivar not getting set on NSManagedObject Subclass为什么我的 ivar 没有在 NSManagedObject 子类上设置 【发布时间】:2014-02-02 20:47:04 【问题描述】:我有一个使用 CoreData 的项目。我使用 Mogenerator 生成子类。
当我设置一个属性的值时,这个值实际上并没有被赋值。以后每次我尝试设置该值时,我之前设置的值都没有被赋值。
这很好用,因为我的底层数据框架是 Mantle,但是自从迁移到 CoreData 后,它就停止了工作。我依靠 KVO 使一些 UIView 对象与模型保持同步。
同样,CoreData NSManagedObject 子类的 ivars 似乎没有采用我分配给它们的值。
考虑如下界面:
@interface Light : _Light
/**
Light / Color Properties
*/
@property (nonatomic, assign) CGFloat brightness; // 0...1
@property (nonatomic, assign) CGFloat hue; // 0...1
@property (nonatomic, assign) CGFloat saturation; // 0...1
@property (nonatomic, assign, getter = isEnabled) BOOL enabled;
@property (nonatomic, readonly) UIColor *color; // derived from the above
- (void)setHue:(CGFloat)hue saturation:(CGFloat)saturation; // it often makes sense to set these together to generate fewer KVO on the color property.
@end
以及以下 .m 文件:
@interface Light ()
CGFloat _hue, _saturation, _brightness;
UIColor *_color;
@property (nonatomic, assign) BOOL suppressColorKVO;
@property (nonatomic, readwrite) UIColor *color;
@end
@implementation Light
@synthesize suppressColorKVO = _suppressColorKVO;
- (void)setHue:(CGFloat)hue saturation:(CGFloat)saturation
BOOL dirty = NO;
if (saturation != _saturation)
// clamp its value
[self willChangeValueForKey:@"saturation"];
_saturation = MIN(MAX(saturation, 0.0f), 1.0f);
[self didChangeValueForKey:@"saturation"];
dirty = YES;
if (hue != _hue)
[self willChangeValueForKey:@"hue"];
_hue = MIN(MAX(hue, 0.0f), 1.0f);
[self didChangeValueForKey:@"hue"];
dirty = YES;
if (dirty)
if (!_suppressColorKVO)
[self setColor: self.color];
// other stuff... the color accessors are also custom. Derived from the h, s, b values.
@end
我认为我对 CoreData 不满意,但我不知道出了什么问题。这些色调、饱和度、亮度都是“瞬态的”(不是核心数据意义上的),因为它们会被我们与之交互的某些硬件不断更新,因此无需保存它们的状态。
【问题讨论】:
'[self setColor:self.color]' 是什么意思?看起来很奇怪,你覆盖了颜色getter方法吗? 是的,别担心。 ;-) 两者都是自定义的,我这样做是因为颜色是派生的,而 setColor 会发送 KVO。那不是问题。它工作得很好。是 ivars 没有保持我为它们设置的值。 【参考方案1】:如果 hue
和 saturation
是模型中的属性,那么您应该使用 setPrimitiveValue:forKey:
(或相关的生成的原始方法)设置它们的值。
也就是说,您的代码看起来都是自定义的,因为模型属性将是 NSNumber
实例,并且 mogenerator 会为您创建值方法。所以我猜测你拥有的这些属性在模型中没有得到支持,这就是它们没有被存储的原因。
因此,将属性添加到模型并使用适当的方法访问值。
【讨论】:
我会在今天晚些时候处理它时这样做。根本不是 CoreData 专家,您是说将我自己的 ivars 保持在“CoreData 模型之外”(即不声明,并由我自己的访问器管理,就好像它是 NSObject 的直接子类一样)不起作用?我更愿意这样做,因为它们真的太临时了,我想把 CoreData 排除在外。 托管对象不是这样设计的。如果你想这样做,你应该使用一个普通的对象。 不能使用普通对象。无论如何,为了真正追查这个问题的根源,我采取了这个问题行为,将其与我的应用程序的其余功能隔离,将其放入测试/沙箱项目中,并注意到我没有看到问题了。所以我猜我上面描述的问题并不是全部。当我找到问题的根源时,我会更新。【参考方案2】:最终它与CoreData无关。上面的这种方法确实适用于 CoreData 对象。您可以在子类中拥有一些存在于 CoreData NSManagedObject 之外的“瞬态”属性,并且您可以为它们创建自己的 ivars,以及您自己的访问器,并且它可以合作。
关于这个问题,我有一个复杂的系统,它也向某些硬件发送一些命令,硬件返回响应是否接受当前状态的命令。事实证明我在那个处理程序中有一个错误,它将这些值设置回一些意外的值。
帮助我调试它的是在调试器中使用观察点。非常方便的功能!您设置了一个观察点,只要变量的内存地址设置为新值,它就会在调试器中中断。 (一点点more on that here)
【讨论】:
以上是关于为啥我的 ivar 没有在 NSManagedObject 子类上设置的主要内容,如果未能解决你的问题,请参考以下文章
为啥在 init 方法中为 iVar 定义调用 autorelease?
如果 @protected 是默认值,为啥这个 ivar 需要 @protected?