我正在选择一些核心数据条目并对其进行排序。这很简单,但由于按距离排序的计算,我想把它放在另一个线程中。#ifdef THREADS
我通过在下面的部分中添加代码为另一个线程创建一个新的 NSManagedObjectController 来做到这一点。
现在我可以进行提取,然后进行排序和组织,而不会减慢用户界面的速度,并且表格将在准备好后进行更新。
但是,由于我在本地托管对象上下文中进行获取,因此我获取的对象在我的主线程上无效 - 实际上它们从我的表格视图单元格中消失了。
所以,我的问题是:1)使用主托管对象上下文是否可以,因为我只是在阅读,而不是创建本地上下文?2) 在排序和组织之后,我是否应该使用搜索托管对象上下文对象中的 ObjectID 值从主线程上的主托管对象上下文中重新获取所有对象?3)我是否应该在主托管对象上下文中进行提取,然后使用线程PerformBlockAndWait
上返回的对象进行排序和组织?searchQ
4)我还没有想到的其他东西?
- (void) fetchShopLocations {
#ifdef THREADS
dispatch_queue_t searchQ = dispatch_queue_create( "searchQueue", NULL );
dispatch_async( searchQ, ^{
#endif
NSError *error;
#ifdef THREADS
// Make a managed object context that can be not on the main thread
NSManagedObjectContext *localContext = [[NSManagedObjectContext alloc] init];
[localContext setPersistentStoreCoordinator: [self.managedObjectContext persistentStoreCoordinator]];
#else
NSManagedObjectContext *localContext = self.managedObjectContext;
#endif
// Get the array of locations sorted by distance
NSArray *locations = NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName: NSStringFromClass([Shop class])];
// No sort descriptors since I cannot sort on things not in the database
NSArray *locations = [context executeFetchRequest: request error: &error];
if( !locations ) {
NSLog( @"Shop fetch error: %@", error );
return;
}
locations = [locations sortedArrayUsingComparator: ^NSComparisonResult( Shop *loc1, Shop *loc2 ) {
double dist1 = [loc1 distanceFromLatitude: self.referenceLatitude andLongitude: self.referenceLongitude];
double dist2 = [loc2 distanceFromLatitude: self.referenceLatitude andLongitude: self.referenceLongitude];
if( dist1 < dist2 )
return NSOrderedAscending;
else if( dist1 > dist2 )
return NSOrderedDescending;
return [[loc1 name] localizedCaseInsensitiveCompare: [loc2 name]];
}];
NSMutableArray *sections = [NSMutableArray arrayWithCapacity: 5];
NSMutableDictionary *section;
NSMutableArray *rows;
section = [NSMutableDictionary dictionaryWithCapacity: 2];
rows = [NSMutableArray arrayWithCapacity: locations.count];
__block double sectionLimitUserUnits = 5.0;
__block double sectionLimitKilometers;
if( self.userUnits == LocationDistanceUnitsMiles )
sectionLimitKilometers = sectionLimitUserUnits * KILOMETERS_PER_MILE;
else sectionLimitKilometers = sectionLimitUserUnits;
[section setValue: [NSString stringWithFormat: @"Within %g", sectionLimitUserUnits] forKey: kSectionHeaderTitleKey];
[locations enumerateObjectsUsingBlock: ^( Shop *loc, NSUInteger idx, BOOL *stop ) {
double distance = [loc distanceFromLatitude: self.referenceLatitude andLongitude: self.referenceLongitude];
if( distance > self.maxDistance ) {
*stop = YES;
} else {
while( distance > sectionLimitKilometers ) {
[section setValue: [rows copy] forKey: kRowKey];
[sections addObject: [section copy]];
[section removeAllObjects];
[rows removeAllObjects];
sectionLimitUserUnits += 5.0;
if( self.userUnits == LocationDistanceUnitsMiles )
sectionLimitKilometers = sectionLimitUserUnits * KILOMETERS_PER_MILE;
else sectionLimitKilometers = sectionLimitUserUnits;
[section setValue: [NSString stringWithFormat: @"Within %g", sectionLimitUserUnits] forKey: kSectionHeaderTitleKey];
}
[rows addObject: loc];
}
}];
[section setValue: [rows copy] forKey: kRowKey];
[sections addObject: [section copy]];
#ifdef THREADS
dispatch_async( dispatch_get_main_queue(), ^{
#endif
self.sections = sections;
[self.tableView reloadData];
#ifdef THREADS
});
});
dispatch_release( searchQ );
#endif
}
由于线程冲突的不确定性,我知道我不能仅仅依赖于测试在模拟器中似乎可以工作的东西。
提前致谢!