具有谓词/排序功能闭包的NSFetchRequest

时间:2014-06-05 23:10:43

标签: ios core-data swift

我正在重建我的应用程序的CoreData堆栈,并将使用带有泛型的工作单元/存储库模式。

我的设置是BaseRepository<T:NSObject>泛型类以及从基础存储库继承的CoreDataRepository<T:NSManagedObject>类。

我有四种检索方法:getAllgetAllSortedgetAllFiltered,最后是getAllFilteredSorted

CoreDataRepository会将前三个get方法链接到最后一个方法,并传入默认值。

以下是指定方法的定义:

func getAllFilteredSorted(predicate:(T) -> Bool, comparer:(T, T) -> Bool) -> T[]
    {
        let request = NSFetchRequest(entityName: entityName)
        let results = context.executeFetchRequest(request, error: nil)

        // TODO: Set predicate in Swift
        // TODO: Set sort descriptors in Swift

        return results as T[]
    }

但是,我找不到使用这些函数闭包创建NSPredicateNSSortDescriptors的方法。 NSManagedObjectContext.executeFetchRequest(...)也没有超载来接受它们。

我知道可以在事实之后对进行排序/过滤,但这会减少我的CoreData请求的优化。我之前更愿意这样做。

关于如何实现这一目标的任何想法?如果我可以将闭包转换为适当的对象,我不介意,我只是不想改变我的函数的参数定义。

1 个答案:

答案 0 :(得分:2)

归功于@David,但这属于答案,而不仅仅是评论。

不要做Swifty事情,因为他们是Swifty。为工作带来正确的工具。

您确实可以使用Swift闭包进行排序和过滤:

// NSPredicate:
init(block block: (AnyObject!, [NSObject : AnyObject]!) -> Bool) -> NSPredicate
// NSSortDescriptor:
init(key key: String, ascending ascending: Bool, comparator cmptr: NSComparator)
// where...
typealias NSComparator = (AnyObject!, AnyObject!) -> NSComparisonResult

但不要。

如果您的数据已经是内存中对象图的一部分,那么使用Swift中的闭包进行排序和过滤非常有用 - 您可以与这些对象交谈,询问他们的属性,并根据您获得的回复做出决策。您可以将此形式称为命令式编程 - 您正在告诉机器确切地要做什么(&#34;给我这些数据。获取此属性。与此相比属性。返回NSOrderedAscending。&#34; ),它完全符合您的要求。

但是当您使用Core Data时,您正在使用的数据不一定是对象 - 它们可能是SQLite数据库中的行,或者归功于{{{ 1}}子类,实际上几乎任何东西,本地或远程。在这种情况下,命令式编程会中断...您不想从数据库中获取所有内容(或从任何地方获取),将每行转换为NSIncrementalStore,从每个行读取属性等。 (想象一下,如果您的数据库特别大,或者您的Core Data存储由远程服务支持,会发生什么。)

相反,你想要的是描述性编程:告诉机器你通常想做什么,并让它弄清楚如何最好地完成结果。 (&#34;为我提供名称中包含&#39; foo&#39;或&#39;フー&#39;的项目,按创建日期按升序排序。&#34; )是NSManagedObjectNSSortDescriptor之类的类 - 它们是通用的(在Swift语言意义上不是通用的)方式来描述如何对数据进行排序和过滤。程序(或像Core Data这样的库)可以自由阅读这些描述并实现它们,但最适合于手头的任务。

在使用本地SQLite存储运行Core Data的情况下,您的谓词和排序描述符将变为SQL查询,因此无需实例化和处理对象 - 排序和过滤发生得更多有效地在后端,只有结果才需要构建对象。实际上,我相信如果您尝试使用SQL后端执行基于块/闭包的谓词或比较器,至少有一些Core Data API会给您一个错误。