Как правильно использовать insertRowsAtIndexPaths?

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

Мой метод "добавить" делает это:

- (IBAction) toggleEnabledTextForSwitch1onSomeLabel: (id) sender {  
if (switch1.on) {

    NSArray *appleComputers = [NSArray arrayWithObjects:@"WWWWW" ,@"XXXX", @"YYYY", @"ZZZZ", nil];
    NSDictionary *appleComputersDict = [NSDictionary dictionaryWithObject:appleComputers forKey:@"Computers"];
    [listOfItems replaceObjectAtIndex:0 withObject:appleComputersDict];
    [tblSimpleTable reloadData];

}

Что работает, но анимации нет. Я понимаю, что для добавления анимации мне нужно использовать insertRowsAtIndexPaths: withRowAnimation, поэтому я попробовал множество опций, но всегда сбой при выполнении метода insertRowsAtIndexPaths: withRowAnimation.

Моя недавняя попытка заключалась в следующем:

- (IBAction) toggleEnabledTextForSwitch1onSomeLabel: (id) sender {  
if (switch1.on) {

    NSIndexPath *path1 = [NSIndexPath indexPathForRow:1 inSection:0]; //ALSO TRIED WITH indexPathRow:0
      NSArray *indexArray = [NSArray arrayWithObjects:path1,nil];   
     [tblSimpleTable insertRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationRight];

}
}  

Что я делаю неправильно? Как я могу сделать это легко? Я не понимаю всю эту вещь indexPathForRow... Я также не понимаю, как с помощью этого метода я могу добавить имя метки в новую ячейку. Пожалуйста, помогите... спасибо!

Ответ 1

При использовании insertRowsAtIndexPaths важно помнить, что ваш UITableViewDataSource должен соответствовать тому, что говорит ему вставка. Если вы добавите строку в представление таблицы, убедитесь, что данные резервной копии уже обновлены, чтобы они соответствовали.

Ответ 2

Это двухэтапный процесс:

Сначала обновите свой источник данных, чтобы numberOfRowsInSection и cellForRowAtIndexPath вернули правильные значения для ваших данных после вставки. Вы должны сделать это, прежде чем вставлять или удалять строки, или вы увидите ошибку "недопустимое количество строк", которое вы получаете.

Затем вставьте строку:

[tblSimpleTable beginUpdates];
[tblSimpleTable insertRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationRight];
[tblSimpleTable endUpdates];

Простое вставка или удаление строки не изменяет ваш источник данных; вы должны сделать это сами.

Ответ 3

Прежде всего, вы должны обновить свою модель данных непосредственно перед самой таблицей обновлений. Также вы можете использовать:

[tableView beginUpdates];
// do all row insertion/delete here
[tableView endUpdates];

И таблица будет производить все сразу с анимацией (если вы ее укажете)

Ответ 4

insertRowsAtIndexPaths:withRowAnimation: И изменения в вашей модели данных должны иметь место между beginUpdates и endUpates

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

@interface MyTableViewController ()
@property (nonatomic, strong) NSMutableArray *expandableArray;
@property (nonatomic, strong) NSMutableArray *indexPaths;
@property (nonatomic, strong) UITableView *myTableView;
@end

@implementation MyTableViewController

- (void)viewDidLoad
{
    [self setupArray];
}

- (void)setupArray
{
    self.expandableArray = @[@"One", @"Two", @"Three", @"Four", @"Five"].mutableCopy;
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.expandableArray.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    //here you should create a cell that displays information from self.expandableArray, and return it
}

//call this method if your button/cell/whatever is tapped
- (void)didTapTriggerToChangeTableView
{
    if (/*some condition occurs that makes you want to expand the tableView*/) {
        [self expandArray]
    }else if (/*some other condition occurs that makes you want to retract the tableView*/){
        [self retractArray]
    }
}

//this example adds 1 item
- (void)expandArray
{
    //create an array of indexPaths
    self.indexPaths = [[NSMutableArray alloc] init];
    for (int i = theFirstIndexWhereYouWantToInsertYourAdditionalCells; i < theTotalNumberOfAdditionalCellsToInsert + theFirstIndexWhereYouWantToInsertYourAdditionalCells; i++) {
        [self.indexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
    }

    //modify your array AND call insertRowsAtIndexPaths:withRowAnimation: INBETWEEN beginUpdates and endUpdates
    [self.myTableView beginUpdates];
    //HERE IS WHERE YOU NEED TO ALTER self.expandableArray to have the additional/new data values, eg:
    [self.expandableArray addObject:@"Six"];
    [self.myTableView insertRowsAtIndexPaths:self.indexPaths withRowAnimation:(UITableViewRowAnimationFade)];  //or a rowAnimation of your choice

    [self.myTableView endUpdates];
}

//this example removes all but the first 3 items
- (void)retractArray
{
    NSRange range;
    range.location = 3;
    range.length = self.expandableArray.count - 3;

    //modify your array AND call insertRowsAtIndexPaths:withRowAnimation: INBETWEEN beginUpdates and endUpdates
    [self.myTableView beginUpdates];
    [self.expandableArray removeObjectsInRange:range];
    [self.myTableView deleteRowsAtIndexPaths:self.indexPaths withRowAnimation:UITableViewRowAnimationFade];  //or a rowAnimation of your choice
    [self.myTableView endUpdates];
}

@end

Ответ 5

Для быстрых пользователей

// have inserted new item into data source

// update
self.tableView.beginUpdates()
var ip = NSIndexPath(forRow:find(self.yourDataSource, theNewObject)!, inSection: 0)
self.tableView.insertRowsAtIndexPaths([ip], withRowAnimation: UITableViewRowAnimation.Fade)
self.tableView.endUpdates()