Сортировка основных данных по отношению ко многим в UITableView
Я видел много постов здесь, касающихся этой проблемы, но ни один, кажется, не решает проблему, которую я имею.
У меня есть приложение, которое использует основные данные. Я пытаюсь отсортировать tableView, который подключен к NSFetchedResultsController, что делает проблему более сложной, чем некоторые другие посты здесь, это то, что мне нужно обновить сортировку на основе местоположения пользователей.
Мой сценарий выглядит следующим образом:
У меня есть сущность под названием Store. Магазин имеет много филиалов, каждый филиал имеет свой lat / long. У меня есть табличное представление, которое отображает все ветви для выбранного магазина. Я хочу, чтобы, когда пользователь обновлял свое местоположение, в то время как вид таблицы виден, ячейки обновляют свою позицию так, чтобы вид таблицы сортировался с ближайшей ветвью вверху.
Мне удается заставить все это работать правильно, когда анимация ячеек перемещается вверх и вниз, когда пользователь перемещается ближе к ветви и т. Д. Однако мое решение не только неэффективно, но и содержит серьезную ошибку, когда в виде таблицы больше ячеек, чем может поместиться на экране.
Я знаю, что наиболее вероятный путь - использование NSOrderedSet для сортировки отношения ко многим в моей сущности Store. Но не уверен, как реализовать это, поскольку значение, по которому я сортирую, не хранится в основных данных, а вычисляется динамически, если это имеет смысл. Широта и долгота сохраняются, но расстояние вычисляется на лету и его значение расстояния, которое определяет сортировку.
В настоящее время я использую протокол locactionManager: didUpdateLocations протокола CLLocationManger для вызова updateCellSortingOrder, который является моим методом сортировки. Менеджер местоположения настроен на:
self.manager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
Мой метод сортировки работает, но, как я уже сказал, он не идеален. Я хочу использовать как можно больше основных инструментов данных, таких как NSFetchedViewController, предикаты, агрегаты и т. Д., А не создавать массивы, сортировать их, затем возвращать их обратно в FRC и т. Д., Что-то вроде того, что я делаю сейчас.... все слишком грязно
Вот мой код, обратите внимание: branchCell является подклассом UITableViewCell, который имеет свойство init, содержащее ветвь. Филиал является экземпляром моей сущности Филиал
//Creating the branch cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"MyTableCellView";
BranchCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[BranchCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
Branch *currentBranch = [[self.list.listsToDelivery allObjects] objectAtIndex:indexPath.row];
cell.branch = currentBranch;
cell.textLabel.text = currentBranch.title;
}
return cell;
}
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
//update the cells
[self updateCellSortingOrder];
}
- (void) updateCellSortingOrder
{
// get the number of cells
static int numberOfCells;
numberOfCells = [[self.currentStore.branches allObjects] count];
//loop though all the cells
for (int cellAIndex = 0; cellAIndex < numberOfCells; cellAIndex++)
{
//set up the cells
static BranchCell * cellA;
static BranchCell * cellB;
//branch instances
static Branch *branchA;
static Branch *branchB;
//distances
static CLLocationDistance distanceA;
static CLLocationDistance distanceB;
static CLLocation *locationA;
static CLLocation *locationB;
//second loop to get the next cell
for (int cellBIndex = cellAIndex+1; cellBIndex < numberOfCells; cellBIndex++)
{
//assign the cells
cellA = (BranchCell *)[self.myTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:cellAIndex inSection:0]];
cellB = (BranchCell *)[self.myTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:cellBIndex inSection:0]];
//get the two branches which we need to compate
branchA = cellA.branch;
branchB = cellB.branch;
//calculate the distance
locationA = [[CLLocation alloc] initWithLatitude:branchA.address.region.center.latitude longitude:branchA.address.region.center.longitude];
locationB = [[CLLocation alloc] initWithLatitude:branchB.address.region.center.latitude longitude:branchB.address.region.center.longitude];
distanceA = [self.manager.location distanceFromLocation:locationA];
distanceB = [self.manager.location distanceFromLocation:locationB];
//move the cell a to cell b's location if a's distances is greater than b's
if (distanceA > distanceB)
{
[self.myTableView moveRowAtIndexPath:[NSIndexPath indexPathForRow:cellAIndex inSection:0] toIndexPath:[NSIndexPath indexPathForRow:cellBIndex inSection:0]];
}
}
}
}
1 ответ
Если кто-то столкнулся с той же проблемой, что и я, вот мое решение. Исправлено некоторое время назад, но никогда не обновлялось. Он был использован в моем приложении Delivered, которое сейчас находится в магазине приложений:)
updateCellSortingOrder вызывается на методе делегата карты mapView: didUpdateUserLocation:
(void) updateCellSortingOrder {
[self.myTableView reloadData];
[self.sortedCellArray sortUsingComparator: ^ (Delivery * deliveryA, Delivery * deliveryB) {
CLLocationDistance distanceA; CLLocationDistance distanceB; distanceA = [[self.mapView userLocation] distanceFromLocation: deliveryA.address]; distanceB = [[self.mapView userLocation] distanceFromLocation: deliveryB.address]; if ( distanceA > distanceB) { return (NSComparisonResult)NSOrderedDescending; } return (NSComparisonResult)NSOrderedSame;
}];
}