我有entity
个对象。这些对象包含Latitude
和longitude
。我还添加了一个transient attribute
range
来计算范围。请看下面的课程:
@implementation Relation
@dynamic firstLetter;
@dynamic rel_address;
@dynamic rel_balanceTotal;
@dynamic rel_bank_country_code;
@dynamic rel_bank_number;
@dynamic rel_city;
@dynamic rel_city_id;
@dynamic rel_code;
@dynamic rel_country;
@dynamic rel_country_code;
@dynamic rel_customerProspect;
@dynamic rel_email;
@dynamic rel_expired_total;
@dynamic rel_fax;
@dynamic rel_gsm;
@dynamic rel_name;
@dynamic rel_phone;
@dynamic rel_turnovertotal;
@dynamic rel_vat_country_code;
@dynamic rel_vat_number;
@dynamic rel_website;
@dynamic rel_zipcode;
@dynamic rel_longitude;
@dynamic rel_latitude;
@dynamic range;
-(NSNumber *)range{
NSNumber *rangeFromCurrentLocation;
[self willAccessValueForKey:@"range"];
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
CLLocation *location = [[CLLocation alloc]initWithLatitude:[self.rel_latitude floatValue] longitude:[self.rel_longitude floatValue]];
CLLocation *location2 = [[CLLocation alloc]initWithLatitude:appDelegate.latitude longitude:appDelegate.longitude];
CLLocationDistance distance = [location2 distanceFromLocation:location]; // distance is expressed in meters
CLLocationDistance kilometers = distance / 1000.0;
float floatrange = ceil(kilometers / 5.0) * 5;
rangeFromCurrentLocation = [NSNumber numberWithFloat:floatrange];
[self didAccessValueForKey:@"range"];
NSLog(@"RANGE IS %@",rangeFromCurrentLocation);
return rangeFromCurrentLocation;
}
我想要做的是建立一个包含5公里,10公里,15公里的路段的列表.... 在启动时,我只加载半径为5km的关系。我是这样做的。
_searchDistance = 2.50;
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
float minLat = appDelegate.latitude - (_searchDistance / 69);
float maxLat = appDelegate.latitude + (_searchDistance / 69);
float minLon = appDelegate.longitude - _searchDistance / fabs(cos(appDelegate.longitude / 180.0 * M_PI)*69);
float maxLon = appDelegate.longitude + _searchDistance / fabs(cos(appDelegate.longitude / 180.0 * M_PI)*69);
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:@"Relation" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"rel_latitude <= %f AND rel_latitude >= %f AND rel_longitude <= %f AND rel_longitude >= %f", maxLat, minLat, maxLon, minLon];
[fetchRequest setPredicate:predicate];
NSSortDescriptor *sort = [[NSSortDescriptor alloc]
initWithKey:@"rel_name" ascending:YES selector:@selector(caseInsensitiveCompare:)];
[fetchRequest setSortDescriptors:[NSArray arrayWithObjects:sort,nil]];
这是正常的,我只获取radius of 5km
内的对象。在我的tableView的底部,我有一个load more button
,我在其中更改了_searchDistance
(我又添加了5公里)
要构建我的列表,请使用此NSFetchedresultController
:
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:context sectionNameKeyPath:@"range"
cacheName:nil];
问题
当视图加载时,每件事都可以。但是当我点击加载更多时,我得到一个空列表并在我的日志中得到此错误
CoreData: error: (NSFetchedResultsController) The fetched object at index 6 has an out of order section name '10. Objects must be sorted by section name'
2014-04-23 12:01:27.673 Adsolut[2097:60b] Unresolved error Error Domain=NSCocoaErrorDomain Code=134060 "The operation couldn’t be completed. (Cocoa error 134060.)" UserInfo=0x167630f0 {reason=The fetched object at index 6 has an out of order section name '10. Objects must be sorted by section name'}, {
reason = "The fetched object at index 6 has an out of order section name '10. Objects must be sorted by section name'";
任何帮助将不胜感激! 提前谢谢!
答案 0 :(得分:1)
问题是所有对象首先按照第一个排序描述符进行排序,
然后根据sectionNameKeyPath
分组成各个部分。
有关此参数的documentation个说明:
如果此键路径与第一个排序指定的路径不同 在fetchRequest中的描述符,它们必须生成相同的相对 排序
这意味着您必须使用排序所有对象的第一个排序描述符 根据他们到当前位置的距离。不幸的是,这种排序描述符 只能使用持久性属性。但是(据我所知)没有办法解决这个问题 如果使用获取的结果控制器,则限制。
答案 1 :(得分:0)
我同意@Martin R。
我使用的方法是在我的NSFetchedResultsController
中构建逻辑,这样,如果它存在,第一个排序描述符总是section
,其他排序描述符被添加到排序描述符数组中第二,第三,第四等
通过这种方式,您可以保护FRC免受当前遇到的崩溃的影响。
<强> UPDATE ... 强>
除了讨论之外,我还包括了一些我编辑过的方法来准备FRC,其中包括防止您遇到的崩溃。如上所述,这可能不适用于瞬态属性。
此代码在触发方法之前设置了以下公共属性。
@property (nonatomic, strong) NSString *entity;
@property (nonatomic, strong) NSString *sectionIdentifier;
@property (nonatomic, strong) NSString *sortAttributePrimary;
@property (nonatomic, strong) NSString *sortAttributeSecondary;
@property (nonatomic, strong) NSString *sortAttributeTertiary;
@property (nonatomic, strong) NSString *sortAttributeQuaternary;
@property (nonatomic, strong) NSPredicate *requestPredicate;
@property (nonatomic, strong) NSString *cacheName;
这些属性中的每一个都由调用FRC的实体对象设置。默认情况下,sortAttributePrimary = nil
存在值时设置sectionIdentifier
。
另请注意,(BOOL)userSettingListsSortAscending
是NSUserDefault
,也是在此方法的第一部分中确定的,但是已被删除以尝试将代码保持在合理的大小。
- (void)configureFetch {
if (self.managedObjectContext) {
...< other code including preparation of NSPredicate>...
// Prepare and set Sort Descriptors
NSArray *requestSortDescriptors = nil;
NSSortDescriptor *sortDescriptorPrimary = nil;
NSSortDescriptor *sortDescriptorSecondary = nil;
NSSortDescriptor *sortDescriptorTertiary = nil;
NSSortDescriptor *sortDescriptorQuaternary = nil;
if (self.sortAttributePrimary != nil) {
sortDescriptorPrimary = [NSSortDescriptor sortDescriptorWithKey:self.sortAttributePrimary ascending:userSettingListsSortAscending selector:@selector(compare:)];
} else if (self.sortAttributePrimary == nil) {
sortDescriptorPrimary = [NSSortDescriptor sortDescriptorWithKey:self.sectionIdentifier ascending:userSettingListsSortAscending];
}
if (self.sortAttributeSecondary != nil) {
sortDescriptorSecondary = [NSSortDescriptor sortDescriptorWithKey:self.sortAttributeSecondary ascending:userSettingListsSortAscending selector:@selector(compare:)];
}
if (self.sortAttributeTertiary != nil) {
sortDescriptorTertiary = [NSSortDescriptor sortDescriptorWithKey:self.sortAttributeTertiary ascending:userSettingListsSortAscending selector:@selector(compare:)];
}
if (self.sortAttributeQuaternary != nil) {
sortDescriptorQuaternary = [NSSortDescriptor sortDescriptorWithKey:self.sortAttributeQuaternary ascending:userSettingListsSortAscending selector:@selector(compare:)];
}
if (sortDescriptorPrimary != nil) {
if (sortDescriptorSecondary != nil) {
if (sortDescriptorTertiary != nil) {
if (sortDescriptorQuaternary != nil) {
requestSortDescriptors = [NSArray arrayWithObjects: sortDescriptorPrimary, sortDescriptorSecondary, sortDescriptorTertiary, sortDescriptorQuaternary, nil];
} else if (sortDescriptorQuaternary == nil) {
requestSortDescriptors = [NSArray arrayWithObjects: sortDescriptorPrimary, sortDescriptorSecondary, sortDescriptorTertiary, nil];
}
} else if (sortDescriptorTertiary == nil) {
requestSortDescriptors = [NSArray arrayWithObjects: sortDescriptorPrimary, sortDescriptorSecondary, nil];
}
} else if (sortDescriptorSecondary == nil) {
requestSortDescriptors = [NSArray arrayWithObjects: sortDescriptorPrimary, nil];
}
}
NSLog(@"%@ - %@ - sortDescriptors are: %@_", self.className, NSStringFromSelector(_cmd), requestSortDescriptors);
[fetchRequest setSortDescriptors:requestSortDescriptors];
// Set fetchedResultsController
if (self.sectionIdentifier == nil || [self.sectionIdentifier isEqualToString:@""]) {
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:self.cacheName];
} else {
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:self.sectionIdentifier cacheName:self.cacheName];
}
self.fetchedResultsController.delegate = self;
} else {
self.fetchedResultsController = nil;
}
}
最后值得注意的是,我使用compare:
而不是localizedCaseInsentiveCompare:
进行排序,因为有时我的排序描述符之一是NSDate
。