在我之前的问题中试图弄清楚确切的问题是什么之后:
fetchedObjects (NSArray) count return 0 when it's full of objects
我很确定我需要我的核心数据与多个类和线程异步。
我尝试连续多次调用我的核心数据,一个接一个,我没有问题。
但显然我需要从多个类和线程读取/写入它。
我使用 @synchronized
进行了验证,但仍然没有,我在核心数据的 fetchedObjects
数组中有 0 条记录,但其中有数据。
正确的做法是什么?
编辑 1:
如果我尝试使用 NSTimer 安排上面的代码,则它只能运行一次:
TrapService.mm:
self.managedObjectContext = appDelegate.managedObjectContext;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:kCORE_DATA_ALL_TRAPS_ENTITY inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSError *error = nil;
NSArray *fetchedObjects = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
NSLog(@"fetchedObjects.count: %d", fetchedObjects.count);
编辑 2:
我使用核心数据的另一个代码示例,执行一次,然后所有关于核心数据的操作什么也不做,或者返回包含 0 条记录的数组。
TrapService.mm:
- (void)initializeQuadTree
{
self.qTree = [[QuadTree alloc] init];
self.qTree = [dbat addCoordinatesToQuadTree:self.qTree];
}
- (Traps*)getCloseTrapFromTree:(CLLocation*)location
{
return [dbat getCloseTrapFromTree:self.qTree andLocation:location];
}
DataBaseAllTraps.m:
- (QuadTree*)addCoordinatesToQuadTree:(QuadTree*)quadTree
{
if (quadTree == nil) {
quadTree = [[QuadTree alloc] init];
}
BOOL success = YES;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:kCORE_DATA_ALL_TRAPS_ENTITY inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSError *error = nil;
NSArray *fetchedObjects = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects == nil || fetchedObjects.count == 0)
{
NSLog(@"addCoordinatesToQuadTree - localizedDescription: %@, userInfo: %@", error.localizedDescription, error.userInfo);
success = NO;
}
NSLog(@"addCoordinatesToQuadTree - fetchedObjects.count: %d", fetchedObjects.count);
if (success)
{
for (CoreDataAllTraps *trap in fetchedObjects)
{
double latitude = trap.lat.doubleValue;
double longitude = trap.lon.doubleValue;
double closePointLat = trap.close_point_lat.doubleValue;
double closePointLon = trap.close_point_lon.doubleValue;
DummyAnnotation *trapAnnotation = [[DummyAnnotation alloc] init];
if (closePointLat != 0.0 || closePointLon != 0.0) trapAnnotation.coordinate = CLLocationCoordinate2DMake(closePointLat, closePointLon);
else trapAnnotation.coordinate = CLLocationCoordinate2DMake(latitude, longitude);
[quadTree insertObject:trapAnnotation];
}
}
else
{
for (Traps *trap in kNETROADS_CONTEXT.arrayOfAllTraps)
{
double latitude = trap.lat;
double longitude = trap.lon;
double closePointLat = trap.closePointLat;
double closePointLon = trap.closePointLon;
DummyAnnotation *trapAnnotation = [[DummyAnnotation alloc] init];
if (closePointLat != 0.0 || closePointLon != 0.0) trapAnnotation.coordinate = CLLocationCoordinate2DMake(closePointLat, closePointLon);
else trapAnnotation.coordinate = CLLocationCoordinate2DMake(latitude, longitude);
[quadTree insertObject:trapAnnotation];
}
}
NSLog(@"TOTAL NUMBER OF TRAPS (%s): %i", __PRETTY_FUNCTION__, success?fetchedObjects.count:[Netroads sharedInstance].arrayOfAllTraps.count);
return quadTree;
}
- (Traps*)getCloseTrapFromTree:(QuadTree*)quadTree andLocation:(CLLocation*)location
{
NSLog(@"%s", __PRETTY_FUNCTION__);
NSArray *closeTraps = [quadTree neighboursForLocation:location.coordinate limitCount:1];
if (closeTraps.count == 0) { return nil; }
// NSAssert(closeTraps.count > 0, @"closeTraps.count == 0, get close trap from quad tree.");
int trapID = 0;
DummyAnnotation *trapLocation = closeTraps.firstObject;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:kCORE_DATA_ALL_TRAPS_ENTITY inManagedObjectContext:self.managedObjectContext];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%@ == %f AND %@ == %f", CLOSE_POINT_LAT, trapLocation.coordinate.latitude, CLOSE_POINT_LON, trapLocation.coordinate.longitude];
[fetchRequest setEntity:entity];
[fetchRequest setPredicate:predicate];
[fetchRequest setFetchLimit:1];
NSError *error = nil;
NSArray *fetchedObjects = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects != nil && fetchedObjects.count > 0) { // We have close point
CoreDataAllTraps *trap = fetchedObjects.firstObject;
trapID = trap.trapID.intValue;
}
else { // We do not have close point, use normal coordinates (lat, lon)
NSLog(@"%s error: %@\n%@", __PRETTY_FUNCTION__, error.localizedDescription, error.userInfo);
fetchRequest = [[NSFetchRequest alloc] init];
entity = [NSEntityDescription entityForName:kCORE_DATA_ALL_TRAPS_ENTITY inManagedObjectContext:self.managedObjectContext];
predicate = [NSPredicate predicateWithFormat:@"%@ == %f AND %@ == %f", LAT, trapLocation.coordinate.latitude, LON, trapLocation.coordinate.longitude];
[fetchRequest setEntity:entity];
[fetchRequest setPredicate:predicate];
[fetchRequest setFetchLimit:1];
error = nil;
fetchedObjects = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects != nil && fetchedObjects.count > 0) {
CoreDataAllTraps *trap = fetchedObjects.firstObject;
trapID = trap.trapID.intValue;
}
else {
NSLog(@"%s error: %@\n%@", __PRETTY_FUNCTION__, error.localizedDescription, error.userInfo);
}
}
if (trapID > 0) {
return [self getTrap_trapID:trapID];
}
else {
return nil;
}
}
编辑 3:
我正在创建一个新的 MOC,但仍然没有,同样的问题:
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
[context setPersistentStoreCoordinator:appDelegate.persistentStoreCoordinator];
最佳答案
我没有分析你的代码。 (我太懒了。:-))但是当我搜索一个存档时,我什么也没找到。
请记住,发生了什么:在标准设置中,您有一个 SQL-DB 作为后端。每个线程/队列都有不同的上下文,它们(部分)在获取请求时取出 SQL-DB 的数据,并(部分)在保存请求时保存它。
没有上下文自动将其更改(包括插入和删除)推送到数据库或另一个上下文。没有上下文会自动从数据库或另一个上下文中提取另一个上下文推送的更改。因此,必须以“手动”方式将数据从上下文传输到另一个上下文。
只要您没有删除,您就可以在一个上下文使用保存完成时简单地存储数据,并在另一个线程上收听保存通知。
关于ios - 来自多个类和线程的异步核心数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21826633/