为了获得缓存结果,查询需要匹配(或等于)缓存结果的较早查询。问题中发布的查询每次都不一样,因为它是由[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 功能的好处在于,在连接的情况下,您的维护查询仍然与服务器保持相对最新,因为在查询之后,会静默进行,如果可能的话,会进行真正的查询,并出现新实例。当然,有些会过期,因为时间已经过去了,但是我们之后会使用内存过滤器来解决这个问题。