【问题标题】:Connecting remote search results with local database using CoreData使用 CoreData 将远程搜索结果与本地数据库连接
【发布时间】:2016-06-02 11:53:18
【问题描述】:

假设我们有一个单一实体User 的简单数据模型;简单的 tableView_friends 和 fetchedResultsController_friends 用于显示用户 - 朋友。

假设我们有搜索栏用于搜索服务中的所有(不仅是朋友)用户,并且对于输入的每个字符,我们都会向服务器执行搜索请求,服务器会以某种方式通过字符用户过滤返回给我们对象。其中一些对象可能已经在本地数据库中。根据应用程序逻辑,我们并不是真的必须将所有这些结果永远保存在本地数据库中(但是好的,我们可以,我们可以不时清除本地数据库);另一方面,如果我们要对某个搜索到的用户执行任何操作,我们必须存储这个用户。我们想在其他tableView_search 和fetchedResultsController_search 中显示搜索到的用户列表。

问题:我应该为fetchedResultsController_friends 和fetchedResultsController_search 使用相同的上下文吗?如果没有,当我希望编辑已在数据库中存在并且可能已经在本地编辑的搜索用户时,我该如何处理?如果是,我如何为fetchedResultsController_search 设置谓词(服务器执行自己的按字符搜索逻辑,可以更改)以显示与服务器完全相同的结果?

【问题讨论】:

    标签: ios objective-c swift uitableview core-data


    【解决方案1】:

    我们最近在我们的应用程序中实现了一个搜索功能并且遇到了类似的问题,我们在核心数据中有本地数据,还有来自我们 API 的远程数据。

    我们探索了几个选项:

    1. 将您的数据保存到 API 中的核心数据中,因为它被检索并 然后获取的结果控制器将完成剩下的工作
    2. 自己管理数据的合并,在一定程度上仍然可以使用 NSFetchedResults 控制器,但需要做更多的工作

    我们不想保存从 API 返回的所有信息,除非需要(用户选择了它),因此我们想出了一个适用于我们的应用的简单解决方案。这可能不适用于您的应用,您可能需要完全不同的解决方案或更改我们所做的一些事情以适应。

    首先,为了解释我们正在处理的内容,我们在核心数据中有一个 Article 实体,它包含大约 25 个属性,API 将文章对象作为 JSON 数据返回,具有相同的数据。

    我们决定做的是创建一个类来表示文章的简单版本(刚好足够的数据显示在列表视图中并稍后在 API 或核心数据中引用它),看起来像这样:

    class SearchResult: NSObject {
    
        var id:String?
        var title:String?
        var imageUrl:String?
        var url:String?
    
        // core data entity
        init(article:Article) {
            self.id = content.contentId
            self.title = content.title
            self.featuredImageURL = content.absoluteImagePath()
            self.urlAlias = content.urlAlias
            self.publishedAt = content.publishedAt
        }
    
        init(articleDictionary:NSDictionary) {
            self.id = articleDictionary.objectForKeyNotNull("id") as? String
            self.title = articleDictionary.objectForKeyNotNull("title") as? String
            self.url = articleDictionary.objectForKeyNotNull("url") as? String
    
            if let imageUrl = articleDictionary.objectForKeyNotNull("imageUrl") as? String {
                self.imageUrl = imageUrl
            }
        }
    }
    

    现在使用它,我们可以从核心数据结果或 API 结果中创建一次。我们的 tableview 数据源只是一个数组

    var dataSet = [SearchResult]()
    

    我们使用 NSFectchResultsController 委托方法在初始加载后从数据集中添加/删除/重新排序核心数据元素,当我们获得 API 数据时,我们将执行以下操作:

    dataSet = Array(Set(apiResponseArray + dataSet))
    

    这将从 API 中获取一组 SearchResult 项,将它们与当前结果集合并并删除重复项。转换为一个集合然后再转换回一个数组将为您提供一个唯一结果数组,因为 Set 仅由唯一值组成。

    请参阅此reference,它应该有助于了解委托方法的工作方式

    【讨论】:

    • 感谢您的出色回答!我是对的,您保持服务器上的搜索方法清晰并且本地数据库的应用程序中的谓词工作完全相同?您是一步收到服务器搜索请求的所有数据还是分批收到的?我是否认为如果我滚动到 25.000 行,那么 dataSet.count 将 >= 25.000?
    • 我们对远程 API 搜索结果进行分页,这样我们一次会收到大约 20 个,并且可以滚动任意数量。如果您正在搜索本地内容和远程数据,您应该确保搜索大致相同以获得相关结果。如果您滚动到 25k 的行,那么是的,您的计数可能是 25k,因为您不太可能拥有服务器上不存在的任何本地内容。
    • 让我想象一下,您有标题为 aaa 和 azz 的文章,存储在本地数据库中,并且您执行远程搜索键“a” .这是否意味着,在每次请求之后(直到您从服务器获得一次 azz 文章)您的tableView 中的最后一行总会有文章 azz?我的意思是在tableView 中是这样的:firstRequest: aaa, aab, aac, ..., aay, azz; secondRequest: aaa, aab, aac, ..., aay, aaz、aba、abb、...、abx、azz
    • 这取决于您的实施,我们按发布日期对我们的内容进行排序
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-26
    • 1970-01-01
    • 2014-12-15
    • 2011-12-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多