Метод добавления события добавляет ячейку сверху, а не снизу

#iphone #objective-c

#iPhone #objective-c

Вопрос:

У меня есть следующий метод, который добавляет ячейку в tableview. Я хочу, чтобы добавленная ячейка была внизу, однако прямо сейчас она добавляет ее вверху. Есть предложения?

Метод addEvent:

 -(void)addEvent
{    
    Routine *routine = (Routine *)[NSEntityDescription insertNewObjectForEntityForName:@"Routine" inManagedObjectContext:managedObjectContext];

    routine.name=entered;

    NSError *error = nil;
    if (![managedObjectContext save:amp;error]) {
        // Handle the error.
    }
    NSLog(@"%@", error);

    [eventsArray insertObject:routine atIndex:0];

    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];

    [self.routineTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];

    [self.routineTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
     }
  

viewDidLoad

 - (void)viewDidLoad
{
    if (managedObjectContext == nil) 
    { 
        managedObjectContext = [(CurlAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext]; 
    }

    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Routine" inManagedObjectContext:managedObjectContext];
    [request setEntity:entity];

    NSError *error = nil;
    NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:amp;error] mutableCopy];
    if (mutableFetchResults == nil) {
        // Handle the error.
    }
    [self setEventsArray:mutableFetchResults];
    [mutableFetchResults release];
    [request release];

    UIBarButtonItem * addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(showPrompt)];
    [self.navigationItem setLeftBarButtonItem:addButton];
    [addButton release];

    UIBarButtonItem *editButton = [[UIBarButtonItem alloc]initWithTitle:@"Edit" style:UIBarButtonItemStyleBordered target:self action:@selector(toggleEdit)];
    self.navigationItem.rightBarButtonItem = editButton;
    [editButton release];

    [super viewDidLoad];
}
  

Ответ №1:

0 это первый индекс. Как правило (вероятно, где-то в мире есть несколько исключений), все, что связано с индексами, начинается с 0. Тогда как такие вещи, как count начинаются с 1.

Итак, если у вас есть массив с 1 объектом в нем, количество массива будет 1 , а объект будет иметь индекс 0 .

Когда вы используете 0, для вашей indexPath строки и раздела вы указываете ему поместить его в начало tableview.

Поэтому сделайте последние 4 строки кода примерно такими:

 [eventsArray addObject:routine];

NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];

[self.routineTableView reloadData];

NSInteger lastSection = [self.routineTableView numberOfSections] -1;

[self.routineTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:[self.routineTableView numberOfRowsInSection:lastSection]-1 inSection:lastSection] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
  

Комментарии:

1. Да, я понимаю это, я пытался сделать [self.routineTableView insertRowsAtIndexPaths:[eventArray count] withRowAnimation:UITableViewRowAnimationFade]; , но при этом я получаю ошибку. Есть другие идеи?

2. По той же причине количество будет на 1 больше, чем индекс. Поскольку счетчик начинается с 1, но индекс начинается с 0. Вам нужно сделать [self.routineTableView insertRowsAtIndexPaths:[eventArray count]-1 withRowAnimation:UITableViewRowAnimationFade];

3. Лично я бы просто использовал reloadData, как у меня в моем ответе

4. Спасибо, Джонатан, я пытался реализовать этот код, но не могу заставить [self.routineTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:[self.routineTableView numberOfCellsInSection:lastSection]-1 inSection:lastSection] atScrollPosition:UITableViewScrollPositionBottom animated:YES]; работать. Перед компиляцией я получаю сообщение об ошибке: семантическая проблема и выход из-под контроля и т.д.

5. Arithmetic on pointer to interface id, which is not a constant size in non-fragile ABI

Ответ №2:

Вероятно, используйте [eventsArray AddObject:] вместо insertObject:atIndex:

Кроме того, вы должны иметь возможность использовать [self.routineTableView reloadData]; вместо того, чтобы вставлять строки вручную — при условии, что вы настроили контроллер представления таблицы обычным способом.

Комментарии:

1. Спасибо, picciano. Не могли бы вы подробнее остановиться на этом? Есть ли лучший способ обновить таблицу с помощью reloadData, а не так, как я это делаю?

Ответ №3:

Конкретный ответ на ваш вопрос заключается в том, что в вашей таблице в качестве источника данных используется массив, и вы добавляете новый элемент в начало массива. Поэтому, когда таблица перезагружается, новая ячейка оказывается вверху.

Для более глубокого понимания я рекомендую вам как минимум ознакомиться со следующими темами:

  1. распространенные типы данных, используемые в качестве источников данных с таблицами (в основном, массивы и словари)

  2. как работают табличные представления (например, что такое TableView.DataSource и TableView.delegate)

  3. методы перезагрузки таблицы при изменении источника данных (то, что вы сделали, нормально, но не всегда то, что вы хотите)

Комментарии:

1. Спасибо Xjones, не могли бы вы, пожалуйста, рассказать мне о перезагрузке таблицы и о том, как я должен это сделать в соответствии с тем, что я сделал? Спасибо.

2. Самый распространенный способ — это то, что рекомендовал @picciano. Используйте [tableView reloadData] . Это загрузит всю таблицу. Другие методы вставки, удаления и загрузки определенных разделов и строк описаны в документах UITableView. Они чаще всего используются, когда вы хотите, чтобы пользовательское взаимодействие изменило источник данных и анимировало изменение таблицы.

3. Вам следует изучить кое-что еще. Я вижу, вы используете Core Data для хранения своих routine данных. Похоже, что вы также поддерживаете отдельный массив, eventsArray который содержит ваши routine экземпляры. С этим связано несколько проблем. Вы должны использовать NSFetchedResultsController в качестве источника данных. Опять же, документы Apple помогут вам начать, и если у вас есть конкретные вопросы, ищите и / или задавайте здесь. Удачи!

4. Я не публиковал весь код, но в моем viewDidLoad у меня есть запрос на выборку и [self setEventsArray:mutableFetchResults]; . Разве это не правильный способ сделать это? Я добавлю код к моему первоначальному вопросу.

5. Вы можете использовать запрос на выборку, но сохранение массива событий за пределами базы данных — это то, что доставит вам неприятности. Особенно, если ваше приложение когда-либо изменяет данные из нескольких контроллеров / потоков. NSFetchedResultsController использует запрос на выборку, но явно предназначен для управления представлениями таблиц и предоставления своему делегату соответствующих уведомлений на основе изменений модели данных для соответствующего обновления таблицы. Прочитайте документы, и вы поймете. Я бы не стал добавлять это к этому вопросу, здесь это не совсем актуально.