UITableView добавляет новые строки вниз с анимацией без перезагрузки всей таблицы

У меня есть UITableView, и я хочу иметь возможность добавлять новые строки в нижнюю часть с анимацией, я использовал tableView reloadData, и это работало нормально, но мне нужна анимация. Поэтому я тоже переключился на tableView reloadSections, но проблема в том, что я скажу, что 7 строк видны, что они оживляют все 7 из этих строк. Мне нужно только оживить добавление новой строки, а не каждую строку на экране, как будто она добавляется.

Любая идея, как это сделать?

Ответ 1

В UITableView вы можете вызвать метод

- (void) insertRowsAtIndexPaths:(NSArray*) indexPaths
              withRowAnimation: (UITableViewRowAnimation) animation

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

//
//  InsertingNewRowToBottomOfTableViewController.m
//  Testing-Code-Snippets
//

#import "InsertingNewRowToBottomOfTableViewController.h"

@interface InsertingNewRowToBottomOfTableViewController ()
@end

#define kTestResuseCellIdentifier @"kTestResuseCell"

@implementation InsertingNewRowToBottomOfTableViewController
{
    NSMutableArray *testArray;
}

- (void) viewDidLoad
{
    [super viewDidLoad];
    self->testArray = [[NSMutableArray alloc] initWithArray:@[@"Test 1", @"Test 2", @"Test 3"]];

    UIRefreshControl *customRefreshControl = [[UIRefreshControl alloc] init];
    customRefreshControl.backgroundColor = [UIColor purpleColor];
    [customRefreshControl addTarget:self action:@selector(onRefresh:) forControlEvents:UIControlEventValueChanged];
    self.refreshControl = customRefreshControl;
}

- (void) didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}

- (void) onRefresh: (UIRefreshControl*) refreshControl
{
    [refreshControl endRefreshing];
    [self->testArray addObject:[NSString stringWithFormat:@"Test %lu", self->testArray.count + 1]];
    [self.tableView insertRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:self->testArray.count - 1 inSection:0]] withRowAnimation:UITableViewRowAnimationLeft];
    NSLog(@"Added a new cell to the bottom!");
}

#pragma mark - Table view data source

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

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


- (UITableViewCell*) tableView: (UITableView*) tableView cellForRowAtIndexPath: (NSIndexPath*) indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kTestResuseCellIdentifier forIndexPath:indexPath];
    cell.textLabel.text = [self->testArray objectAtIndex:indexPath.row];
    return cell;
}
@end

Обновление: версия Swift 3

import UIKit

class InsertingNewRowToBottomOfTableViewController: UITableViewController
{
    private let testResuseCellIdentifier:String = "kTestResuseCell"
    private let testArray:NSMutableArray = NSMutableArray(array:["Test 1", "Test 2", "Test 3"])

    // MARK: - View Events

    override func viewDidLoad()
    {
        super.viewDidLoad()

        let refreshControl:UIRefreshControl = UIRefreshControl()
        refreshControl.backgroundColor = UIColor.purple
        refreshControl.addTarget(self, action:#selector(self.onRefresh(refreshControl:)), for:.valueChanged)
        self.refreshControl = refreshControl
    }

    override func didReceiveMemoryWarning()
    {
        super.didReceiveMemoryWarning()
    }

    // MARK: - UIRefreshControl

    @objc private func onRefresh(refreshControl: UIRefreshControl)
    {
        refreshControl.endRefreshing()
        testArray.add("Test \(self.testArray.count + 1)")

        let indexPath:IndexPath = IndexPath(row:(self.testArray.count - 1), section:0)
        self.tableView.insertRows(at:[indexPath], with: .left)
        NSLog("Added a new cell to the bottom!")
    }

    // MARK: - UITableViewDataSource

    override func numberOfSections(in tableView: UITableView) -> Int
    {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
    {
        return self.testArray.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
    {
        let cell:UITableViewCell = tableView.dequeueReusableCell(withIdentifier:testResuseCellIdentifier)!
        cell.textLabel?.text = self.testArray.object(at: indexPath.row) as? String
        return cell
    }
}