【问题标题】:NSFetchedResultsController not sorting on encrypted attributesNSFetchedResultsController 未对加密属性进行排序
【发布时间】:2012-10-02 11:42:26
【问题描述】:

我正在尝试使用可转换类型加密我的核心数据模型中的属性,但是一旦数据被持久化到 sqlite db,我在尝试取回结果时遇到了很多问题。我的核心数据的主要应用程序是存储一些与用户相关的数据并按名字、姓氏等排序再次将其取回,然后使用名字/姓氏的第一个字母作为部分标题将其显示在表格视图中。似乎加密干扰了结果,因为当我尝试使用 NSFetchedResultsController 使用 lastName 作为排序描述符来获取请求时,我什么也没得到。我收到以下错误:

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源加密核心数据属性:

【问题讨论】:

    标签: objective-c ios xcode sqlite core-data


    【解决方案1】:

    《Core Data Programming Guide》中有一些相关信息。

    您无法使用基于瞬态属性的谓词进行获取 (尽管您可以使用瞬态属性在内存中进行过滤 你自己)。 ...总而言之,但是,如果您直接执行 fetch,您应该 通常不会将基于 Objective-C 的谓词或排序描述符添加到 获取请求。相反,您应该将这些应用于 获取。

    抓取和商店类型之间存在一些交互。 ...另一方面,SQL 存储编译谓词和排序 描述 SQL 并评估数据库本身的结果。 这主要是为了性能,但这意味着评估 发生在非 Cocoa 环境中,因此排序描述符(或 依赖于 Cocoa 的谓词)无法工作。

    由于在从 SQLite 存储中获取数据后将转换器应用于数据,因此使用转换后的属性作为排序键将不会产生所需的结果。

    您的Core Data错误可能是由于使用加密数据对部分进行排序,但是FRC的sectionNameKeyPath(可以是临时属性)给出了未加密的数据,这当然是不一致的。

    我能想到的唯一解决方案是存储一个额外的未加密属性,该属性有足够的信息用作排序键(例如人的首字母)。

    【讨论】:

    • 这正是我所做的,但每个人名的第一个字母并不是最好的排序方式,因为 Frank 和 Franz 等名字可能会出现故障。这是因为我必须使用第一个首字母作为排序键以及 sectionkey 以避免相同的错误。即初始作为sectionkey 和fullname 作为sortkey 不起作用。更不用说我的搜索功能也因使用转换后的属性而损坏。我收到以下错误stackoverflow.com/questions/12920541/…
    • @JohnBaum:不幸的是,我没有更好的主意,因为所有过滤和排序都是在 SQLite 级别完成的。 - 唯一的选择是获取所有数据并在之后对其进行排序/过滤,但这样您就失去了获取结果控制器的所有优势。
    • 一旦我获取所有数据并自己过滤它,是否有一种方法可以用来强制为获取的结果控制器分配对象?除非我真的必须这样做,否则我不想放弃获取结果控制器的分段和其他优化
    • @JohnBaum:我不这么认为。 - 您在考虑对 FRC 进行哪些优化?如果您自己获取/过滤数据,那么您将无法再使用 FRC 委托函数来更新事件。
    • 好吧,我真的不想考虑获取的控制器隐藏的切片/查看详细信息(即按第一个首字母进行的切片)
    【解决方案2】:

    据我所知,NSFetchRequest(当您通过 CoreData 使用 sqlite 时)会生成 sql,在 sqlite 上使用它并返回结果。因此,虽然 sqlite 对 CoreData 进行的解密一无所知,但不可能使用 NSFetchRequest 使用解密的数据对结果进行排序。

    可能的解决方案是将 NSFetchRequest 的结果复制到 NSArray 并手动对加密字段进行排序。另一种解决方案是在每次插入或修改时对数据进行排序,并将顺序写入特定的整数字段,然后在对该字段进行获取排序时(如果您执行插入和修改的频率低于获取频率,则会节省您的性能)。

    【讨论】:

      【解决方案3】:

      您描述的错误发生是因为对数据库中的加密数据进行了排序,但NSFetchedResultsController 后来对未加密的数据起作用,并抱怨因为数据未正确排序为节名称。

      要在数据库中排序,您必须提供足够的未加密信息进行排序,并保持该信息是最新的。

      例如,对于按名字排序,您可以存储一个未加密的属性firstNameSection,其中包含firstName 的第一个字母,以及一个属性firstNameSortInfo,其中包含每个索引的该名称的位置(例如例如“Aaron”=0、“Abby”=1 等

      然后您可以使用firstNameSectionfirstNameSortInfo 进行排序,并将firstNameSection 用作sectionNameKeyPath。这种方法有(至少)两个缺点:

      1. 您必须保持firstNameSortInfo 是最新的,这将需要比您希望的更多的写入,并且firstNameSortInfo 排序必须在内存中完成(因为它是在未加密的情况下完成的)数据)。
      2. 潜在的攻击者可能知道有关加密数据的某些信息,这可能会削弱加密。

      【讨论】:

        猜你喜欢
        • 2013-07-21
        • 2013-01-16
        • 2015-07-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-05
        • 2011-07-29
        相关资源
        最近更新 更多