Сортировка основных данных по отношению ко многим в 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;
    

    }];

}

Другие вопросы по тегам