Swift + CoreData。从DB中获取N个随机对象。 N <&lt;大小(DB)

时间:2015-12-23 21:48:45

标签: ios swift core-data

我正在尝试制作app,需要从CoreData获取N个随机对象。

问题是数据库大小远远大于我想要的对象数量。因此,希望有一种不影响数据库中所有记录的方法。

是否可以在不向数据库添加额外字段的情况下实现此目的(例如,id)?

我想收到对请求的不同回复,因此选项&#34;使用一些随机函数预先排序&#34;没有用。

3 个答案:

答案 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)")
}