我正在尝试使用可转换类型加密我的Core Data模型中的属性,但是一旦数据被持久化到sqlite db,我就会遇到很多尝试获取结果的问题。我对Core Data的主要应用是存储一些与用户相关的数据,然后按照名字,姓氏等重新获取它,然后使用名/姓的第一个字母作为节标题在表视图中显示它。似乎加密干扰了结果,因为当我尝试使用lastName作为排序描述符的NSFetchedResultsController进行获取请求时,我什么也得不到。我收到以下错误:
CoreData: error: (NSFetchedResultsController) The fetched object at index X has an out of order section name 'S. Objects must be sorted by section name'
我花了很多时间调查这个问题无济于事。有谁知道问题可能是什么以及如何解决它?在变换器解密数据后,是否有可能对数据库进行排序?或者有没有办法可以获取原始数据,然后在NSFetchedResultsController的实例中获取数据后对其进行排序?
我使用this来源加密核心数据属性:
答案 0 :(得分:1)
“核心数据编程指南”中有一些相关信息。
您无法使用基于瞬态属性的谓词进行提取 (尽管您可以使用瞬态属性在内存中进行过滤 你自己)。 ...总而言之,如果直接执行提取,则应该 通常不会添加基于Objective-C的谓词或排序描述符 获取请求。相反,你应该将这些应用于结果 获取。
提取和商店类型之间存在一些交互。 ...另一方面,SQL存储编译谓词和排序 SQL的描述符并在数据库本身中评估结果。 这主要是为了表现,但这意味着评估 发生在非Cocoa环境中,所以排序描述符(或 (依赖于Cocoa的谓词)不起作用。
由于在从SQLite存储中提取数据后将变换器应用于数据,因此使用转换后的属性作为排序键将不会产生所需的结果。
您的核心数据错误可能是由于使用加密数据对部分进行排序这一事实造成的,但FRC的sectionNameKeyPath
(可以是瞬态属性)会提供未加密的数据,当然这是不一致。
我能想象的唯一解决方案是存储一个额外的未加密属性,该属性具有足够的信息用作排序键(例如,该人的首字母)。
答案 1 :(得分:1)
您描述的错误发生是因为排序发生在数据库中的加密数据上,但NSFetchedResultsController
稍后会对未加密的数据起作用,并抱怨,因为数据未按部分名称正确排序。
要在数据库内部排序,您必须提供足够的未加密信息进行排序,并使该信息保持最新。
例如,要按名字排序,您可以存储未加密的属性firstNameSection
,其中包含firstName
的第一个字母,以及属性firstNameSortInfo
,其中包含该位置每个索引的名称(例如“Aaron”= 0,“Abby”= 1等等
然后,您可以使用firstNameSection
和firstNameSortInfo
进行排序,将firstNameSection
用作sectionNameKeyPath
。这种方法有(至少)两个缺点:
firstNameSortInfo
最新,这需要更多的写入,而firstNameSortInfo
排序必须在内存中完成(因为它是在未加密的数据上完成的。)答案 2 :(得分:1)
据我所知,NSFetchRequest(当您通过CoreData使用sqlite时)生成sql,在sqlite上使用它并返回结果。因此,虽然sqlite对CoreData的解密一无所知,但使用解密数据对NSFetchRequest进行排序是不可能的。
可能的解决方案是将NSFetchRequest的结果复制到NSArray中,并手动对加密字段进行排序。另一种解决方案是在每次插入或修改时对数据进行排序,并将顺序写入特定的整数字段,然后在对该字段进行排序时(如果插入和修改的频率低于提取,则会保存性能)。