保存前修剪核心数据字段

Trimming core data field before saving

我想在将核心数据对象保存到上下文之前对其名称字段进行修整。我的想法是为此使用验证功能。以下实施有效:

@objc
public func validateName(_ value: AutoreleasingUnsafeMutablePointer<AnyObject?>) throws {
    guard let trimmedValue = (value.pointee as? String)?.trimmingCharacters(in: .whitespaces) else {
        return
    }

    if name != trimmedValue {
        name = trimmedValue
    }
}

如果没有if语句只在​​发生变化时设置name字段,core data会因为循环抛出异常

现在我要提问:

  1. 验证函数是执行此操作的最佳方法吗?
  2. 如果您有多个对象的字段必须被修剪,那么上面的代码会非常冗长。我试图创建一个带有 inout 变量值的函数 trimField,并移动了用于修剪、检查更改和设置 inout 变量的代码。但是当我从验证函数中调用它时,由于循环而抛出异常。所以似乎带有 inout 参数的函数确实将字段值设置为“脏”,即使它没有明确设置。还有其他选择吗?

验证之所以这样做,是因为正如您所发现的,只要您设置一个值,就会调用验证函数。要在验证时更改值,您需要使用 setPrimitiveValue(_:forKey:) 而不是像往常一样设置 name 来绕过验证。所以,setPrimitiveValue(trimmed, forKey: "name") 或类似的。

验证可能不是执行此操作的最佳时机。例如,您需要刷新显示对象数据的任何视图。还有一些其他选项。

一个是通过 didChangeValue,像这样:

public override func didChangeValue(forKey key: String) {
    if key == "name", let name = self.name {
        let trimmedValue = nametrimmingCharacters(in: .whitespaces)
        setPrimitiveValue(trimmedValue, forKey: "name")
    }
    super.willChangeValue(forKey: key)
}

您也可以使用 willSave,并使用对象的 changedValues() 查看名称是否更改。

正确的做法——无论如何,就 Core Data 而言——是为 name 覆盖 setter。不幸的是,您需要关闭 Core Data 的自动代码生成才能做到这一点。我在这个答案中描述了这个过程:Using property observers on NSManaged vars