2015-05-05 62 views
2

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

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

回答

2

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

的参数如下:

  1. query:本PFQuery你想执行的查询。
  2. queryBoth:A Bool如果存在从本地数据存储返回的数据,是否要查询分析服务器的值。 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使用以下命令:

参数不同r如下:

  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])") 
} 

为编辑任何建议都非常赞赏。

0

解析有PFQuery一个fromLocalDatastore方法,但我不知道一个notFromLocalDatastore方法的......我能想到的是要做出将返回一个新创建的查询的方法的唯一的事情,那么你可以拨打:

userQuery().fromLocalDatastore().getFirstObjectInBackgroundWithBlock { localR in 
    if let user = localR { 
     //use the user 
    } else { 
     userQuery().getFirstObjectInBackgroundWithBlock { serverR 
      if let user = serverR { 
       //user the user 
      } else { 
       //not even on server - handle somehow... 
      } 
     } 
    } 
} 
相关问题