Ser*_*erd 0 core-data nsfetchedresultscontroller nsfetchrequest ios
NSFetchResultController与NSFetchRequest具有fetchBatchSize = 20总是返回所有实体。它可以是什么?我没有使用 sectionKeyPath 并尝试了不同的排序描述符,但它仍然返回所有对象。
谢谢回复!我会详细说明的。我有一个具有两个字段的实体 - 距离和时间。我已经创建了 NSFetchResultController:
func noticesFetcher() -> NSFetchedResultsController {
let fetchRequest = NSFetchRequest()
let defaultStore = RKManagedObjectStore.defaultStore()
let entity = NSEntityDescription.entityForName("Notice", inManagedObjectContext: defaultStore.mainQueueManagedObjectContext)
fetchRequest.entity = entity
let distanceSortDescriptor = NSSortDescriptor(key: "distance", ascending: true)
let timeSortDescriptor = NSSortDescriptor(key: "time", ascending: false)
let sortDescriptors = [distanceSortDescriptor, timeSortDescriptor]
fetchRequest.sortDescriptors = sortDescriptors
fetchRequest.fetchBatchSize = 20
let resultFetcher = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: defaultStore.mainQueueManagedObjectContext, sectionNameKeyPath: nil, cacheName: nil)
return resultFetcher
}
Run Code Online (Sandbox Code Playgroud)
但是当我执行 fetcher 时,我总是将所有实体都放在数据库中。(100)
func performFetcher(fetcher: NSFetchedResultsController?, filter: NSPredicate?, success: (() -> ())?, failure: ((NSError) -> (NSError))?) -> Bool {
NSFetchedResultsController.deleteCacheWithName(nil)
var resultPerform = false
fetcher?.fetchRequest.predicate = filter
do {
try fetcher?.performFetch()
resultPerform = true
if success != nil {
success!();
}
}
catch let error as NSError {
if failure != nil {
failure!(error)
}
}
return resultPerform
}
Run Code Online (Sandbox Code Playgroud)
它可以是什么?我想得到的结果是分页吸气剂。我知道我可以通过限制和抵消来做到这一点,但这里有什么问题?谢谢
好吧,这取决于您所说的“返回所有实体”是什么意思。我怀疑它会返回一个填充了所有实体的数组。
批量大小一次只能获取(在您的情况下)20 个实体。继续查看 MOC 的注册对象集,您可以轻松验证发生了什么。
您还可以启动仪器并观察单个核心数据提取的发生。
不,批量大小获取不仅仅是“仅 20 个实体”,它获取所有实体。你能做一个测试项目并测试这个批量大小吗?我相信你会有同样的问题 – Serd
@Serd,答案提供者随时为您提供帮助,但我们有时会出错。如果您怀疑他们的回答,那么您应该创建一个测试用例来证明他们所说的是否正确。当你是有问题的人,而他们是免费提供帮助的人时,他们为什么要花额外的时间来这样做?
如果你怀疑答案,那么你就去做工作,如果你发现他们的答案有误,那么要么提供更正,要么提供答案不正确的证据。
但是,您是新来的,希望您能从这次经历中吸取教训,我将向您提供一个简短的演示。
通过向NUM_OBJECTS数据库添加实例来设置测试的 MOC 。
NSUInteger const NUM_OBJECTS = 1000;
NSUInteger const INIT_BATCH_SIZE = 100;
- (void)setUp {
[super setUp];
helper = [[TestHelper alloc] init];
url = [[[NSURL fileURLWithPath:NSTemporaryDirectory()] URLByAppendingPathComponent:[[NSUUID UUID] UUIDString]] URLByAppendingPathComponent:@"foo.sqlite"];
[[NSFileManager defaultManager] createDirectoryAtURL:[url URLByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:NULL];
@autoreleasepool {
NSEntityDescription *noticeEntity = [[NSEntityDescription alloc] init];
noticeEntity.name = @"Notice";
NSAttributeDescription *distance = [[NSAttributeDescription alloc] init];
distance.name = @"distance";
distance.attributeType = NSDoubleAttributeType;
NSAttributeDescription *time = [[NSAttributeDescription alloc] init];
time.name = @"time";
time.attributeType = NSDoubleAttributeType;
noticeEntity.properties = @[distance, time];
NSManagedObjectModel *model = [[NSManagedObjectModel alloc] init];
model.entities = @[noticeEntity];
NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
[psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:nil error:NULL];
moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
moc.persistentStoreCoordinator = psc;
for (NSUInteger count = 0; count < NUM_OBJECTS; ) {
@autoreleasepool {
for (NSUInteger batchCount = 0; batchCount < INIT_BATCH_SIZE && count < NUM_OBJECTS; ++batchCount, ++count) {
NSManagedObject *notice = [NSEntityDescription insertNewObjectForEntityForName:@"Notice" inManagedObjectContext:moc];
double distance = ((double)arc4random_uniform(100000)) / (arc4random_uniform(100)+1);
double time = distance / (arc4random_uniform(100)+1);
[notice setValue:@(distance) forKey:@"distance"];
[notice setValue:@(time) forKey:@"time"];
}
[moc save:NULL];
[moc reset];
}
}
[moc save:NULL];
[moc reset];
}
}
Run Code Online (Sandbox Code Playgroud)
测试后清理...
- (void)tearDown {
[super tearDown];
[[NSFileManager defaultManager] removeItemAtURL:[url URLByDeletingLastPathComponent] error:NULL];
}
Run Code Online (Sandbox Code Playgroud)
几个辅助方法...
- (NSArray*)executeFetchWithBatchSize:(NSUInteger)batchSize {
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Notice"];
fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"distance" ascending:YES],
[NSSortDescriptor sortDescriptorWithKey:@"time" ascending:NO]];
fetchRequest.fetchBatchSize = batchSize;
return [moc executeFetchRequest:fetchRequest error:NULL];
}
- (NSUInteger)numberOfFaults {
NSUInteger numFaults = 0;
for (NSManagedObject *object in moc.registeredObjects) {
if (object.isFault) ++numFaults;
}
return numFaults;
}
Run Code Online (Sandbox Code Playgroud)
使用默认批量大小的测试
- (void)testThatFetchRequestWitDefaultBatchSizeFetchesEverything {
XCTAssertEqual(0, moc.registeredObjects.count);
NSArray *fetched = [self executeFetchWithBatchSize:0];
XCTAssertEqual(NUM_OBJECTS, moc.registeredObjects.count);
XCTAssertEqual(NUM_OBJECTS, fetched.count);
XCTAssertEqual(NUM_OBJECTS, [self numberOfFaults]);
[[fetched objectAtIndex:1] valueForKey:@"distance"];
XCTAssertEqual(NUM_OBJECTS, moc.registeredObjects.count);
XCTAssertEqual(NUM_OBJECTS, fetched.count);
XCTAssertEqual(NUM_OBJECTS-1, [self numberOfFaults]);
}
Run Code Online (Sandbox Code Playgroud)
使用非默认批量大小的测试
- (void)testThatFetchRequestWithExplicitBatchSizeOnlyFetchesTheNumberRequested {
XCTAssertEqual(0, moc.registeredObjects.count);
NSUInteger const BATCH_SIZE = 20;
NSArray *fetched = [self executeFetchWithBatchSize:BATCH_SIZE];
XCTAssertEqual(0, moc.registeredObjects.count);
XCTAssertEqual(NUM_OBJECTS, fetched.count);
XCTAssertEqual(0, [self numberOfFaults]);
[[fetched objectAtIndex:1] valueForKey:@"distance"];
XCTAssertEqual(BATCH_SIZE, moc.registeredObjects.count);
XCTAssertEqual(NUM_OBJECTS, fetched.count);
XCTAssertEqual(BATCH_SIZE-1, [self numberOfFaults]);
}
Run Code Online (Sandbox Code Playgroud)
感谢您的代码!但是我对 NSFetchResultController 和他的 NSFetchRequest 有问题,它有批量大小(它获取所有实体 – Serd
习惯难改。您应该采用我给您的代码并稍微修改它以使用获取的结果控制器进行测试,而不是做出该断言,然后您将自己确认您的断言“它获取所有实体”是不正确的。例如...
稍微修改一下助手...
- (NSFetchRequest*)fetchRequestWithBatchSize:(NSUInteger)batchSize {
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Notice"];
fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"distance" ascending:YES],
[NSSortDescriptor sortDescriptorWithKey:@"time" ascending:NO]];
fetchRequest.fetchBatchSize = batchSize;
return fetchRequest;
}
- (NSArray*)executeFetchWithBatchSize:(NSUInteger)batchSize {
return [moc executeFetchRequest:[self fetchRequestWithBatchSize:batchSize] error:NULL];
}
- (NSFetchedResultsController*)executeFetchUsingFetchedResultsControllerWithBatchSize:(NSUInteger)batchSize {
NSFetchedResultsController *frc = [[NSFetchedResultsController alloc] initWithFetchRequest:[self fetchRequestWithBatchSize:batchSize] managedObjectContext:moc sectionNameKeyPath:nil cacheName:nil];
[frc performFetch:NULL];
return frc;
}
Run Code Online (Sandbox Code Playgroud)
并稍微更改现有测试以添加 FRC 测试。
- (void)testThatFetchRequestWitDefaultBatchSizeFetchesEverythingEvenWithFetchedResultsController {
XCTAssertEqual(0, moc.registeredObjects.count);
NSFetchedResultsController *frc = [self executeFetchUsingFetchedResultsControllerWithBatchSize:0];
XCTAssertEqual(NUM_OBJECTS, moc.registeredObjects.count);
XCTAssertEqual(NUM_OBJECTS, frc.fetchedObjects.count);
XCTAssertEqual(NUM_OBJECTS, [self numberOfFaults]);
[[frc.fetchedObjects objectAtIndex:1] valueForKey:@"distance"];
XCTAssertEqual(NUM_OBJECTS, moc.registeredObjects.count);
XCTAssertEqual(NUM_OBJECTS, frc.fetchedObjects.count);
XCTAssertEqual(NUM_OBJECTS-1, [self numberOfFaults]);
}
- (void)testThatFetchRequestWithExplicitBatchSizeOnlyFetchesTheNumberRequestedEvenWithFetchedResultsController {
XCTAssertEqual(0, moc.registeredObjects.count);
NSUInteger const BATCH_SIZE = 20;
NSFetchedResultsController *frc = [self executeFetchUsingFetchedResultsControllerWithBatchSize:20];
XCTAssertEqual(moc, frc.managedObjectContext);
XCTAssertEqual(0, moc.registeredObjects.count);
XCTAssertEqual(NUM_OBJECTS, frc.fetchedObjects.count);
XCTAssertEqual(0, [self numberOfFaults]);
[[frc.fetchedObjects objectAtIndex:1] valueForKey:@"distance"];
XCTAssertEqual(BATCH_SIZE, moc.registeredObjects.count);
XCTAssertEqual(NUM_OBJECTS, frc.fetchedObjects.count);
XCTAssertEqual(BATCH_SIZE-1, [self numberOfFaults]);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1357 次 |
| 最近记录: |