【问题标题】:PFQuery cache is null all the timePFQuery 缓存一直为空
【发布时间】:2015-08-04 23:55:29
【问题描述】:

我将 PFQuery 对象的缓存策略设置为 kPFCachePolicyCacheThenNetwork,但缓存始终为空。有人可以帮我看看发生了什么吗?

下面的代码将缓存的结果一直返回为空

-(void)doSomeQuery
{
   PFQuery *query = [PFQuery queryWithClassName:kMySpecialClass];
   [query whereKey:kDateExpires greaterThan:[NSDate date]];
   query.cachePolicy = kPFCachePolicyCacheThenNetwork;
   NSLog(@"CACHED ? =  %i",[query hasCachedResult]);//Nope, no matter what returns NO
   [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {


    NSLog(@"RETURNED: %@", objects);//1st cache (null) then network gets the data

  }];

}

【问题讨论】:

    标签: ios objective-c caching parse-platform pfquery


    【解决方案1】:

    为了获得缓存结果,查询需要匹配(或等于)缓存结果的较早查询。问题中发布的查询每次都不一样,因为它是由[NSDate date]限定的。

    为确保查询具有缓存结果,请保留相同的 PFQuery 对象。如果你设置kPFCachePolicyCacheThenNetwork,然后再次运行find...,你会得到一个缓存的结果。

    编辑 - 解决这个问题取决于系统对时间的敏感程度。让我们将查询理解为:给我未过期的 MySpecialClass 实例,其中 unexpired 表示将来过期。

    让我们使用本地缓存来表示,有时我想要快速查询和/或离线操作,并且我愿意牺牲与服务器上的内容相关的真相(也许服务器没有获取新实例无论如何,MySpecialClass 非常频繁)。

    在这些情况属实的情况下,您可以通过两种类型的查询来解决 OP 问题:

    1) 刷新查询,执行频率较低,它会清除缓存并从服务器获取最新的未过期内容。此查询的实现与 OP 代码中完全相同,但使用默认缓存策略:仅网络。

    2) 更频繁地完成的维护查询,它依赖于缓存,但运行速度快且离线。这个查询仍然想省略我的特殊类的过期实例,但我们在查询之后的代码中这样做。将此查询实现为持久的属性(至少在执行期间,可能在执行之间,但这是一个不同的主题)并使用 cache-then-network 如下:

    @property (strong) PFQuery *maintenanceQuery;
    
    // lazily init
    - (PFQuery *)maintenanceQuery {
        if (!_maintenanceQuery) {
           // op code, including cachePolicy = kPFCachePolicyCacheThenNetwork;
        }
        return _maintenanceQuery;
    }
    
    // based on some timing decision, either run the refresh query or...
    - (void)runMaintenanceQuery:(void (^)(NSArray *, NSError *))completion {
        [self.maintenanceQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
            NSDate *now = [NSDate date];
            NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(PFObject *mySpecialInstance, NSDictionary *bind){
                NSDate *expiration = [mySpecialInstance valueForKey:kDateExpires];
                return now == [expiration earlierDate:now];
            }];
    
            NSArray *unexpired = [objects filteredArrayUsingPredicate:predicate];
            completion(unexpired, error);
        }];
    }
    

    cache-then-network 功能的好处在于,在连接的情况下,您的维护查询仍然与服务器保持相对最新,因为在查询之后,会静默进行,如果可能的话,会进行真正的查询,并出现新实例。当然,有些会过期,因为时间已经过去了,但是我们之后会使用内存过滤器来解决这个问题。

    【讨论】:

    • 谢谢@danh 有什么解决办法吗?本地数据存储除外
    • @fzkl - 当然。回答起来不太简单,但我做到了最好。
    【解决方案2】:

    根据文档,kPFCachePolicyCacheThenNetwork 不应第一次从缓存中返回。第一次它应该在返回之前访问网络。可能是你有糟糕的缓存数据或什么?

    • 您能否在不设置 cachePolicy 的情况下确认查询是否正常返回?

    • 其他选项是尝试从设备中删除应用程序并再次运行以清除缓存。以防设备上的缓存数据有任何问题。

    【讨论】:

    • 感谢您的响应,但它首先从缓存返回,然后是网络,如他们的文档中所述。查询始终返回,但缓存将为空。 CacheThenNetwork:查询首先从缓存加载,然后从网络加载。在这种情况下,回调实际上会被调用两次——首先是缓存结果,然后是网络结果。
    猜你喜欢
    • 2015-08-05
    • 1970-01-01
    • 2017-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-28
    • 2012-01-24
    • 1970-01-01
    相关资源
    最近更新 更多