如何在保存到核心数据之前验证上下文中的值

Posted

技术标签:

【中文标题】如何在保存到核心数据之前验证上下文中的值【英文标题】:How to validate the values in the context before saving to core data 【发布时间】:2012-01-03 01:12:28 【问题描述】:

我们如何在将上下文保存到核心数据之前对其进行验证?我的想法是我应该在将其保存到核心数据之前进行一些验证,如果这些值不满足验证,那么核心数据不应该保存这些值。例如,我有实体候选人的名称、类别、年龄等属性。我应该验证这些值不应该为零。如果为 nil,则不应保存其他值。

谁能帮我解决这个问题

编辑: 我只需要在保存时检查它们,并且应该使用核心数据来完成

【问题讨论】:

【参考方案1】:

我喜欢在保存例程中进行全面验证。在你实际调用保存上下文之前,循环遍历它的insertedObjects 数组并确保它们是你需要的。如果不是,您可以删除它们或提醒用户他们需要完成某些事情(如果是后者,请退出该方法;让用户有机会解决问题)。

其他验证应该在入口点,当您从文本字段或复选框中获取值以分配给您的托管对象时。如果有问题,请立即通知用户。

还可以查看 NSNumberFormatter,它可以应用于字段,防止用户一开始就输入错误的条目。

【讨论】:

比如说,我需要一个属性作为键,如果该属性不为零,那么只有上下文中的其他值应该保存到核心数据中。有没有这样的事情? @维恩克 对,我误解了你的问题。我在下面发布了另一个答案。【参考方案2】:

Coredata 在插入其值时验证自身。在 managedObject 类中,我们可以编写自定义验证,以便 coredata 在保存值之前检查该验证。如果该值无效,则上下文中的这些值将不会保存到 coredata。

我在这里添加

@interface
-(BOOL) validateForInsert:(NSError **)error;

@implementation
-(BOOL) validateForInsert:(NSError **)error 
   // check the value of the field with validation
     if(condition == true) 
      return Yes;
     
 return NO;

(NSError **) 是一个特殊的参数,它使 coredata 像委托方法一样调用这个方法

【讨论】:

这里有一些混淆:保存对象就是保存包含对象的上下文——除非对象已经插入到上下文中,否则不会发生这种情况。此外, NSError 不会调用该方法。您通过引用传递一个空的 NSError,如果发生错误,该方法将填充它。【参考方案3】:

抱歉,当我做出第一个答案时,我没有仔细阅读您的问题。您不是在验证各个属性的各个条目是否正确,而是不应保存任何更改,除非为该对象填充了 所有 个属性。

查看 Apple 文档“Model Object Validation”,您关心的是 inter-属性验证,而不是属性验证,并且您正在考虑使用 validateForInsert: 来解决此问题目的。

该文档还提供了示例。这是您描述的特定实体的可能实现:

- (BOOL)validateForInsert:(NSError **)error 
if (self.name && self.class && self.age)
    return [super validateForInsert:error];
else
    return NO;

但是,此方法发生在插入阶段,而不是保存阶段。

如果您同时为一个新实体收集条目,那么在插入阶段进行验证是有意义的——如果该对象注定要作为不完整而被丢弃,则不要将新对象添加到上下文中。 如果您正在收集对现有对象进行更改的条目,并且希望在接受其中任何更改之前确保所有这些更改一起工作,validateForUpdate: 将是有意义的 - 但没有办法将对象恢复到其原始状态状态,而不是重新打开上下文而不保存,除非您已将其原始值缓存在其他地方。 如果您想单独收集 attrs 并在保存对象之前等待检查它们是否都已完成,我认为您会按照我最初建议的方式进行操作:循环遍历上下文的 insertObjects 并在实际保存上下文之前进行验证。没有现有的 validateForSave: 方法可以覆盖,但您可以添加一个。

您还可以结合这些技术:收集条目并创建新对象而不插入它们,但将所有这些对象缓存在一个数组中。当需要保存时,循环通过缓存并仅在对象通过validateForInsert: 时将其插入上下文;然后保存上下文。

显然,我正在和你一起学习,所以上面的内容可能并不完全是 cookie。希望 Apple 文档足以让您入门。

【讨论】:

新链接是:Object Validation。此外,在 validateForInsert: 的前两行中,您混淆了属性级验证 ('[super validateForInsert:error]') 和属性间或一致性验证 (self.name && self.class && self.age) .首先进行属性级验证,然后检查一致性。就您的代码现在而言,无法设置名称、类别或年龄。

以上是关于如何在保存到核心数据之前验证上下文中的值的主要内容,如果未能解决你的问题,请参考以下文章

在保存和从上下文中删除之前验证实体

由于验证规则上下文导致的 iOS 核心数据保存 MOC 问题

在核心数据中保存到托管对象上下文时的 SIGABRT

ios核心数据:如何更改NSManagedObject而不将其保存到上下文中

核心数据 - 管理上下文

核心数据:托管对象与上下文一起保存后如何撤消操作