swift - 同时查询解析服务器和本地数据存储

标签 swift parse-platform

我正在尝试创建一个 PFQuery,其中查询的响应存储在服务器和本地数据存储中。我想创建一个带有约束的查询(query.whereKey()),它将首先查看响应是否存储在设备上,如果没有,它将查询服务器.

例如,我正在加载帖子列表。该应用程序存储当前用户关注的一组用户。对于存储在设备上的用户发布的帖子,我想从数据存储而不是服务器加载用户详细信息(例如他们的个人资料图片和用户名)。但是,如果该帖子是由未存储在设备上的用户发布的,则它将查询服务器。我只能想象用 2 个不同的查询执行此操作,但我更愿意在一个查询中执行此操作。

最佳答案

我在自己的项目中编写了以下内容,并将其发布,以防有​​人正在寻找完整的答案。

参数如下:

  1. query:您要执行查询的 PFQuery
  2. queryBoth:一个 Bool 值,表示如果有从本地数据存储返回的数据,是否要查询 Parse 服务器。 true 将同时查询两者,false 仅在本地数据存储未返回任何内容时才查询服务器。
  3. toCallUponCompletion:从服务器、本地数据存储或两者接收到响应时将调用的闭包(函数)。该函数应该接受 PFObjects 数组并且不返回任何内容。该函数的实现将显示在以下函数下方。

功能:

func findObjectsInBackgroundFromLocalDataStoreIfPossible (query: PFQuery, queryBoth: Bool, toCallUponCompletion: ([PFObject]) -> ()){
    var response = [PFObject]()

    let queryCopy = query.copy() as! PFQuery
    queryCopy.fromLocalDatastore()
    queryCopy.findObjectsInBackgroundWithBlock{
        (objects: [AnyObject]?, error: NSError?) -> Void in
        if error == nil{
            if objects?.count == 0{
                query.findObjectsInBackgroundWithBlock{
                     (objects2: [AnyObject]?, error: NSError?) -> Void in
                    if error == nil{
                        response = objects2 as! [PFObject]
                        toCallUponCompletion(response)
                    }
                }
            }
            else if queryBoth{
                response = objects as! [PFObject]
                var responseObjectIds = [String]()
                for x in response{
                    responseObjectIds.append(x.objectId)
                }
                query.whereKey("objectId", notContainedIn: responseObjectIds)
                query.findObjectsInBackgroundWithBlock{
                    (objects2: [AnyObject]?, error: NSError?) -> Void in
                    if error == nil{
                        response += objects2 as! [PFObject]
                        toCallUponCompletion(response)
                    }
                    else{
                        toCallUponCompletion(response)
                    }
                }
            }
            else{
                response = objects as! [PFObject]
                toCallUponCompletion(response)
            }
        }
        else{
            println("Error being called in 'findObjectInBackgroundFromLocalDataStoreIfPossible' Error is: \(error)")
        }
    }
}

关闭实现:

func storeResponse (response: [PFObject]){
    println(response)
}

要实现与上述函数相同的功能,但使用多个 PFQueries,请使用以下命令:

参数差异如下:

  1. queries:这是您要执行查询的 PFQueries 数组。顺序很重要。
  2. toCallUponCompletion:此闭包采用带有 Int 键和 PFObject 值的字典作为参数,并且不返回任何内容。原因是发送查询时,它们可能无法完成并以相同的顺序返回。因此,字典中每个键值对的键是它的发送顺序,因此可以在不知道响应的实际内容的情况下使用响应。再次引用函数后面的函数闭包的实现。

功能:

func findObjectsInBackgroundFromMultipleQueriesFromLocalDataStoreIfPossible (queries: [PFQuery], queryBoth: Bool, toCallUponCompletion: ([Int: [PFObject]]) -> ()){
    var responses = [Int: [PFObject]]()
    for query in queries{
        var response = [PFObject]()
        let queryCopy = query.copy() as! PFQuery
        queryCopy.fromLocalDatastore()
        queryCopy.findObjectsInBackgroundWithBlock{
            (objects: [AnyObject]?, error: NSError?) -> Void in
            if error == nil{
                if objects?.count == 0{
                    query.findObjectsInBackgroundWithBlock{
                        (objects2: [AnyObject]?, error: NSError?) -> Void in
                        if error == nil{
                            response = objects2 as! [PFObject]
                            responses[find(queries, query)!] = response  
                            if responses.count == queries.count{
                                toCallUponCompletion(responses)
                            }
                        }
                    }
                }
                else if queryBoth{
                    response = objects as! [PFObject]
                    var ids = [String]()
                    for x in response{
                        ids.append(x.objectId)
                    }
                    query.whereKey("objectId", notContainedIn: ids)
                    query.findObjectsInBackgroundWithBlock{
                        (objects2: [AnyObject]?, error: NSError?) -> Void in
                        if error == nil{
                            response += objects2 as! [PFObject]
                            responses[find(queries, query)!] = response
                            if responses.count == queries.count{
                                toCallUponCompletion(responses)
                            }
                         }
                     }
                 }
                 else{
                     response = objects as! [PFObject]
                     responses[find(queries, query)!] = response
                     if responses.count == queries.count{
                         toCallUponCompletion(responses)
                     }
                }
            }
        }
    }
}

关闭实现:

func storeResponses (responses: [Int: PFObject]){
    println("The response to the first query is: \(responses[0])")
    println("The response to the second query is: \(responses[1])")
    println("The response to the third query is: \(responses[2])")
}

非常感谢任何编辑建议。

关于swift - 同时查询解析服务器和本地数据存储,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30055476/

相关文章:

Swiftui - 如何使用 Timer.scheduledTimer 每隔 n 秒应用一次 UiView

ios - 使用步进器更改日期 - Swift

ios - swift -iOS : Remove spaces inside a String before or after any special character

swift - 以编程方式添加 UIBarButtonItem

ios - 无法使用 PFQuery Table ViewController (Swift 2) 显示自定义单元格

java - Parse.com 使用 java 创建 objectId

ios - PFSignupViewController 可选电子邮件

json - 如何使用来自 API 调用的动态变量解码嵌套的 JSON 结构

ios - 使用 Parse 保存数据,现有项目

ios - 解析 PFQuery 使用 PFUSER.query 获取用户数据