我正在尝试制作app,需要从CoreData获取N个随机对象。
问题是数据库大小远远大于我想要的对象数量。因此,希望有一种不影响数据库中所有记录的方法。
是否可以在不向数据库添加额外字段的情况下实现此目的(例如,id)?
我想收到对请求的不同回复,因此选项"使用一些随机函数预先排序"没有用。
答案 0 :(得分:4)
首先计算所有记录:
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"<your entity name>"];
NSUInteger count = [context countForFetchRequest:request error:NULL];
使用fetchOffset
:
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"<your entity name>"];
request.fetchLimit = 1;
request.fetchOffset = arc4random_uniform(count);
NSArray *result = [context executeFetchRequest:request error:NULL];
重复N次以获得所需数量的物体。
答案 1 :(得分:2)
逐个获取n
个对象的问题可能是性能问题。根据{{1}}的大小,这可能无法扩展。
相反,您可以利用Core Data在处理大量对象时非常高效的事实。由于称为“故障”的机制,您可以获取数万个对象,而不会占用太大的内存。
因此,我建议您获取所有对象,然后从结果中选择一些。
n
请注意,另一个优雅的答案是首先 shuffle 数组(如图所示here,然后选择第一个NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Response"];
NSArray *all = [managedObjectContext executeFetchRequest:request error:nil];
NSMutableArray *pickedAnswers = [NSMutableArray array];
int remaining = 10;
if (all.count < remaining) { /* abort */ }
while (remaining > 0) {
Response *response = all[arc4random_uniform(all.count)];
if (![pickedAnswers containsObject:response]) {
[pickedAnswers addObject:response];
remaining--;
}
}
元素)。这将消除n
循环中不必要的运行。
答案 2 :(得分:0)
Swift 5版本
// First count the records
let countRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Dictionary");
do {
let count = try managedObjectContext.count(for: countRequest)
// Then run the query again to choose a random row
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Dictionary");
request.fetchLimit = 5
request.fetchOffset = Int(arc4random_uniform(UInt32(count)))
do {
// Here's your results
let results = try managedObjectContext.fetch(request) as! [Dictionary]
}
catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
}
}
catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
}