1

我正在阅读“核心数据编程指南”。它包含以下文本:

但是,您必须以符合 KVC 的方式更改属性值。例如,以下通常表示编程错误:

NSMutableString *mutableString = [NSMutableString stringWithString:@"Stig"]; [newEmployee setFirstName:mutableString]; [mutableString setString:@"Laura"];

对于可变值,您应该将值的所有权转移给 Core Data,或者实现自定义访问器方法以始终执行复制。如果表示 Employee 实体的类声明了 firstName 属性(副本)(或实现了复制新值的自定义 setFirstName: 方法),则前面的示例可能不会表示错误。在这种情况下,调用 setString: 之后(在第三行代码中)firstName 的值仍然是“Stig”而不是“Laura”。

关于文本的问题:“在这种情况下”是哪种情况 - 属性被声明为“副本”或不是?

关于复制和编程实践的问题:从我在这里读到的内容: NSString 属性:复制还是保留? 我明白

  1. 使用 copy 将确保 firstName 是“Stig”,而不是 Laura
  2. 这样做是明智的,因为“在几乎所有情况下,您都希望防止在其背后改变对象的属性”

我真的很想知道上面引用的文字试图在 Core Data 的上下文中告诉我们什么。无论是否使用 Core Data,我们都必须使用“复制”。另外,如果有人能对上面的“2”点(这是明智的......)进行更多说明,我会很高兴,因为在其背后改变对象的属性会产生什么后果?

4

2 回答 2

1

您的“关于文本的问题:“在这种情况下”是哪种情况 - 属性被声明为“副本”还是不是?我相信,与苹果文件想要解释的观点不符。

正如Apple文档指出的那样,如果自定义访问器方法正常实现,则默认实现不会复制属性值。如果属性值可能是可变的并且实现了 NSCopying 协议(例如 NSString 的情况),您可以将值复制到自定义访问器中以帮助保持封装(例如,在 NSMutableString 的实例是作为值传递)。

这是一个复制设置器片段

@interface Department : NSManagedObject
{
}
@property(nonatomic, copy) NSString *name;
@end
@implementation Department
@dynamic name;
- (void)setName:(NSString *)newName
{
    [self willChangeValueForKey:@"name"];
    // NSString implements NSCopying, so copy the attribute value
    NSString *newNameCopy = [newName copy];
    [self setPrimitiveName:newNameCopy];
    [self didChangeValueForKey:@"name"];
} @end
于 2014-06-28T11:38:33.367 回答
0

问题是何时(以及如何)使用不可变值。

由于核心数据在检测对对象所做的更改时大量使用 KVO,如果您使用直接通过对象而不是通过属性更改的可变属性,CoreData 将不会检测到对对象的更改,并且您的更改可能不会持久保存到存储中.

如果您使用可变的 NSManagedObject 属性,请覆盖 setter/getter 方法并仅使用它们来改变底层对象(这意味着您有责任让 CoreData 知道该对象确实发生了更改,并且必须将其持久化到存储中另外,
如果对复杂对象使用transformable属性,则必须自己触发更改通知,以便CoreData意识到发生了更改,并且在上下文保存时应该重新转换并保存对象。

我强烈建议当涉及到像字符串这样的简单对象时,您使用不可变的属性值,这将强制您通过对象属性并触发默认的 KVO 通知(复制属性也会强制 KVO 通知)。

于 2013-04-13T06:08:12.397 回答