插入时不调用 Core Data 的自定义验证方法

Posted

技术标签:

【中文标题】插入时不调用 Core Data 的自定义验证方法【英文标题】:Custom validation method for Core Data is not called on insert 【发布时间】:2019-01-24 17:14:55 【问题描述】:

我正在快速开发一个使用 Core Data 的 ios 应用程序。我正在尝试实现一些核心数据验证。我还没有任何自定义逻辑,所以我使用模型中的“类定义”设置来让 Xcode 自动创建 NSManagedObject 子类。在这种情况下,根据文档,我可以将验证逻辑放在扩展中。我的代码如下所示:

extension Person 

   func validateEmail(_ value: AutoreleasingUnsafeMutablePointer<AnyObject?>) throws 
        var error: NSError? = nil

    if let email = value.pointee as? String 
        let regex = "^.+@([A-Za-z0-9-]+\\.)+[A-Za-z]2[A-Za-z]*$"
        let predicate = NSPredicate(format: "SELF MATCHES %@", regex)

        if !predicate.evaluate(with: email) 
            let errorType = UserErrorType.invalidEmail
            error = NSError(domain: errorDomain, code: errorType.rawValue, userInfo: [ NSLocalizedDescriptionKey : "The email address is invalid." ] )
        

     else 
        let errorType = UserErrorType.invalidEmail
        error = NSError(domain: errorDomain, code: errorType.rawValue, userInfo: [ NSLocalizedDescriptionKey : "The email address is invalid." ] )
    

    if let error = error 
        throw error
    

不幸的是,我的验证代码永远不会被调用。我知道它只有在实际保存上下文时才会被调用,但它永远不会被调用。我也在尝试:

let entity = NSEntityDescription.entity(forEntityName: "Person", in: self.persistentContainer.viewContext)

let person = NSManagedObject(entity: entity!, insertInto: self.persistentContainer.viewContext) as! Person

person.age = 16
person.hasDrivingLicense = true
person.email = "novalidemail"

do 
    try person.validateForInsert()

    catch 
      let validationError = error as NSError

        print(validationError)
    

但我的验证方法永远不会被调用。我做的另一个测试是在扩展中像这样覆盖 validateValue:

public override func validateValue(_ value: AutoreleasingUnsafeMutablePointer<AnyObject?>, forKey key: String) throws 
    print("\(key)")

最后一个方法会被所有键调用,包括我所追求的“电子邮件”键。

【问题讨论】:

尝试在该方法的实现中调用super.validateValue 谢谢,我试过了,没有成功。 【参考方案1】:

我终于找到了问题。为验证函数添加 @objc 前缀使其工作,因此它被调用。所以,而不是:

func validateEmail(_ value: AutoreleasingUnsafeMutablePointer<AnyObject?>) throws 

只是:

@objc func validateEmail(_ value: AutoreleasingUnsafeMutablePointer<AnyObject?>) throws 

我还没有尝试过这个,因为在来自教程的this 项目中,验证函数没有@objc 前缀并且它们仍然被调用。我想了解其中的区别并发现为什么在我的项目中需要该前缀。谢谢

【讨论】:

请注意,您并没有在代码中自己调用验证函数。当需要验证时,它将由 CoreData 框架调用。 CoreData 是用 Objective-C 编写的。由于 Swift 4 当函数需要被 Objective-C 访问时,需要更加明确。旧代码在 Swift 3 中可以正常运行,但在 Swift 4 中,Objective-C 将不再看到验证函数,因此不会调用它们。感谢分享解决方案。我将一些旧的工作 Swift 代码转换为 Swift 5 并遇到了同样的问题。 XCode 在转换代码时没有警告我。

以上是关于插入时不调用 Core Data 的自定义验证方法的主要内容,如果未能解决你的问题,请参考以下文章

ASP.Net-Core 中的自定义身份验证

Core Data 属性的自定义 Getter

在 Asp.net Core MVC 中定义自定义客户端验证规则

如何为依赖于关系的自定义 Core Data 属性发布通知?

Spring Security Core 和用于确认密码字段的自定义验证器是不是可行?

如何从 ASP.NET Core 2.0 中的自定义中间件请求身份验证