ios – 如何通过核心数据验证将有意义的错误消息反馈给视图控制器?

编辑:我想让大家都知道,自从我发布这个月以来,我一直在努力解决这个问题.现在有一个 repo on github,它显示了如何轻松实现这一目标并保持与KVC的兼容性.没有理由在iOS上避免核心数据验证.它可能与Mac OS X不同,但它并不困难或困难.

我在视图控制器中编辑Person对象的属性. Person是NSManagedobject子类.我正在使用Core Data进行早期(保存前)验证.我正在使用记录的validateValue:forKey:error:这样的方法……

NSError *error;
BOOL isValid = [person validateValue:&firstNameString forKey:@"firstName" error:&error];
if (!isValid) {
    ...
}

我在Xcode的Core Data模型编辑器中设置了最小值和最大值.当我验证firstName并且它太短时我得到这样的错误……

Error Domain=NSCocoaErrorDomain Code=1670 "The operation Couldn’t be completed. (Cocoa error 1670.)" UserInfo=0x8f44a90 {NSValidationErrorObject=<Event: 0xcb41a60> (entity: Event; id: 0xcb40d70 <x-coredata://ADB90708-BAD9-47D8-B722-E3B368598E94/Event/p1> ; data: {
firstName = B;
}),NSValidationErrorKey=firstName,NSLocalizedDescription=The operation Couldn’t be completed. (Cocoa error 1670.),NSValidationErrorValue=B}

但是我没有任何东西可以显示用户.但错误代码在那里,所以我可以做这样的事情……

switch ([error code]) {

        case NSValidationStringTooShortError:
            errorMsg = @"First name must be at least two characters.";
            break;

        case NSValidationStringTooLongError:
            errorMsg = @"First name is too long.";
            break;

    // of course,for real,these would be localized strings,not just hardcoded like this
    }

这在概念上是好的,但firstName和其他Person属性在其他视图控制器上是可编辑的,因此必须在任何视图控制器上编辑firstName时再次实现切换.肯定有更好的办法.

查看属性级验证的核心数据文档揭示了这一点……

If you want to implement logic in addition to the constraints 
you provide in the managed object model,you should not override 
validateValue:forKey:error:. Instead you should implement methods 
of the form validate<Key>:error:.

所以我在Person.m中实现了validateFirstName:error:并且方便地,它通过视图控制器中的现有validateValue:forKey:error:方法执行,就像文档所说的那样.

但是在validateFirstName:error:中,即使firstName太短,错误仍然是nil.当我继续并控制返回到视图控制器时,会出现类似于此问题顶部的错误,但同样,这已经太晚了.我希望在控制时间到达validateFirstName:error:时,firstName将根据模型编辑器中指定的约束进行验证,并且填充的错误对象将通过error参数传入.但事实并非如此.

我留下了两个想法,可能会为转换声明带来一个好的家园……

>在Person.m中实现一个自定义方法,如firstNameValidationForValue:error:.视图控制器将调用方法.在firstNameValidationForValue中:error:call validateValue:forKey:error:.当它返回错误时,构造一个有意义的错误消息,使用该开关,创建一个新的NSError对象并将其返回给视图控制器以供使用.这有效,但它偏离了标准的KVC方法.
>从Xcode中的Core Data模型编辑器中删除所有验证,并执行validateFirstName:error:等方法中的所有验证.根据结果​​,创建一个新的NSError对象并将其返回给视图控制器以供使用.这具有约束和错误消息在相同方法中的优点.而且,与第一个想法不同,继续遵循标准的KVC方法.

你会怎么做?还有另外一种方法吗?

编辑:编辑周期的其他详细信息……

编辑周期从用户点击添加开始.一个新的Person对象被插入到MOC中.视图显示用于编辑的表单,导航栏上显示“取消”和“完成”按钮.用户开始在fieldA中输入数据,完成并点击fieldB.假设fieldA必须在继续之前有效.在fieldB成为第一个响应者之前,fieldA的验证运行.它失败.视图控制器显示从验证返回的错误消息,而fieldA仍然是第一个响应者.用户修复了问题,然后再次点击fieldB.再次验证运行,这次它通过. fieldB成为第一个响应者.这个“添加数据/点击另一个字段或点击下一个/验证/移动到下一个字段与否”过程继续.

重要的是要知道用户可以随时点击取消.在这种情况下,就MOC而言,我所要做的就是[myMOC rollback] ;.

@ImHuntingWabbits:如果我调用save而不是validateValue:forKey:error:该方法存在问题.假设用户在fieldA中输入数据.用户点击fieldB并运行fieldA的验证.此验证使用“保存然后解析错误方法.但假设它通过,所有其他领域也通过.所以现在MOC已经被保存了.但是用户没有点击Done并且可以很好地按下取消.如果用户点击取消,则必须撤消保存.如果模型非常简单但可能非常复杂,那可能相对容易.在我的特殊情况下,我不想采取这种方法.

一个编辑

我们是否可以在github上重新召集:github.com/murraysagal/CoreDataValidationWithiOS我在那里有一个示例应用程序,也许更好地描述了自述文件中的问题.示例应用程序显示,验证通常在iOS上并不困难.该应用程序演示了如何将有意义的错误消息发送回VC并保持完全符合KVC标准.

它讨论了核心数据的两种可能的增强功能,在将它们放到雷达之前,我想要一些反馈.

解决方法

我不会在iOS上使用核心数据验证.核心数据验证是为带有绑定的桌面设计的,而不是针对iOS设计的.

您可以更轻松地在视图控制器中进行验证,并使用核心数据验证作为备份,而不是尝试将核心数据验证连接到用户界面.

更新

Could you explain why you think it will be easier to implement validation on the View Controller level. While proper validation and error handling is never easy,I can’t see a reason why the Core Data level validation should be more complex (besides the issue that validations are possibly performed more than one time,even when it is not required). You also don’t answer the case where there is no VC,or when there are more than one VCs handling objects. Also,certain validations can’t be performed on VC level (e.g. check for uniqueness of certain properties,which is a pain anyway).

当Core Data与用户界面之间存在相当紧密的耦合时,为OS X添加了核心数据验证.这种耦合被称为绑定.使用绑定,立即进入文本字段并“自动添加到与该字段关联的核心数据实体.

此外,当该数据更新时,Core Data可以“回复”验证回到文本字段,以便文本字段可以拒绝数据输入并解释它被拒绝的原因.

这些绑定在iOS上不存在.它们需要手动编写每个数据入口点.

既然我们正在编写这些检查点,那么当我们可以直接将更集中的验证编写到视图控制器中并保存自己的抽象级别时,没有理由尝试挂钩像Core Data的验证这样的通用系统.

在数据导入的情况下,我们再次有一个处理导入的控制器.导入控制器和核心数据之间没有直接连线,所以当我们编写专注的代码解决问题时,我们还有理由尝试插入像Core Data验证这样的通用系统.

通用系统泄漏边缘情况.如果有人花时间来覆盖大多数边缘情况(如Core Data和OS X上的绑定),那么继续使用它们.但是,如果你必须自己覆盖这些边缘或连接代码,那么集成到通用系统中的价值就很小.对于通用系统不是为处理用例而设计的情况尤其如此(例如核心数据验证和iOS).

Core Data的几个部分早于iOS,并且不适合iOS.验证就是其中之一.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


当我们远离最新的 iOS 16 更新版本时,我们听到了困扰 Apple 最新软件的错误和性能问题。
欧版/美版 特别说一下,美版选错了 可能会永久丧失4G,不过只有5%的概率会遇到选择运营商界面且部分必须连接到iTunes才可以激活
一般在接外包的时候, 通常第三方需要安装你的app进行测试(这时候你的app肯定是还没传到app store之前)。
前言为了让更多的人永远记住12月13日,各大厂都在这一天将应用变灰了。那么接下来我们看一下Flutter是如何实现的。Flutter中实现整个App变为灰色在Flutter中实现整个App变为灰色是非常简单的,只需要在最外层的控件上包裹ColorFiltered,用法如下:ColorFiltered(颜色过滤器)看名字就知道是增加颜色滤镜效果的,ColorFiltered( colorFilter:ColorFilter.mode(Colors.grey, BlendMode.
flutter升级/版本切换
(1)在C++11标准时,open函数的文件路径可以传char指针也可以传string指针,而在C++98标准,open函数的文件路径只能传char指针;(2)open函数的第二个参数是打开文件的模式,从函数定义可以看出,如果调用open函数时省略mode模式参数,则默认按照可读可写(ios_base:in | ios_base::out)的方式打开;(3)打开文件时的mode的模式是从内存的角度来定义的,比如:in表示可读,就是从文件读数据往内存读写;out表示可写,就是把内存数据写到文件中;
文章目录方法一:分别将图片和文字置灰UIImage转成灰度图UIColor转成灰度颜色方法二:给App整体添加灰色滤镜参考App页面置灰,本质是将彩色图像转换为灰度图像,本文提供两种方法实现,一种是App整体置灰,一种是单个页面置灰,可结合具体的业务场景使用。方法一:分别将图片和文字置灰一般情况下,App页面的颜色深度是24bit,也就是RGB各8bit;如果算上Alpha通道的话就是32bit,RGBA(或者ARGB)各8bit。灰度图像的颜色深度是8bit,这8bit表示的颜色不是彩色,而是256
领导让调研下黑(灰)白化实现方案,自己调研了两天,根据网上资料,做下记录只是学习过程中的记录,还是写作者牛逼
让学前端不再害怕英语单词(二),通过本文,可以对css,js和es6的单词进行了在逻辑上和联想上的记忆,让初学者更快的上手前端代码
用Python送你一颗跳动的爱心
在uni-app项目中实现人脸识别,既使用uni-app中的live-pusher开启摄像头,创建直播推流。通过快照截取和压缩图片,以base64格式发往后端。
商户APP调用微信提供的SDK调用微信支付模块,商户APP会跳转到微信中完成支付,支付完后跳回到商户APP内,最后展示支付结果。CSDN前端领域优质创作者,资深前端开发工程师,专注前端开发,在CSDN总结工作中遇到的问题或者问题解决方法以及对新技术的分享,欢迎咨询交流,共同学习。),验证通过打开选择支付方式弹窗页面,选择微信支付或者支付宝支付;4.可取消支付,放弃支付会返回会员页面,页面提示支付取消;2.判断支付方式,如果是1,则是微信支付方式。1.判断是否在微信内支付,需要在微信外支付。
Mac命令行修改ipa并重新签名打包
首先在 iOS 设备中打开开发者模式。位于:设置 - 隐私&安全 - 开发者模式(需重启)
一 现象导入MBProgressHUD显示信息时,出现如下异常现象Undefined symbols for architecture x86_64: "_OBJC_CLASS_$_MBProgressHUD", referenced from: objc-class-ref in ViewController.old: symbol(s) not found for architecture x86_64clang: error: linker command failed wit
Profiles >> 加号添加 >> Distribution >> "App Store" >> 选择 2.1 创建的App ID >> 选择绑定 2.3 的发布证书(.cer)>> 输入描述文件名称 >> Generate 生成描述文件 >> Download。Certificates >> 加号添加 >> "App Store and Ad Hoc" >> “Choose File...” >> 选择上一步生成的证书请求文件 >> Continue >> Download。
今天有需求,要实现的功能大致如下:在安卓和ios端实现分享功能可以分享链接,图片,文字,视频,文件,等欢迎大佬多多来给萌新指正,欢迎大家来共同探讨。如果各位看官觉得文章有点点帮助,跪求各位给点个“一键三连”,谢啦~声明:本博文章若非特殊注明皆为原创原文链接。