简体   繁体   中英

iOS - How can I get the IndexPath of the last item in a tableview?

I would like to automatically scroll to the end of a table view.

[tableView scrollToRowAtIndexPath:lastIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];

To get a reference to the last row in the last section…

// First figure out how many sections there are
NSInteger lastSectionIndex = [tableView numberOfSections] - 1;

// Then grab the number of rows in the last section
NSInteger lastRowIndex = [tableView numberOfRowsInSection:lastSectionIndex] - 1;

// Now just construct the index path
NSIndexPath *pathToLastRow = [NSIndexPath indexPathForRow:lastRowIndex inSection:lastSectionIndex];

You can get the indexPath of the last row in last section like this.

NSIndexPath *indexPath = [NSIndexPath indexPathForRow:(numberOfRowsInLastSection - 1) inSection:(numberOfSections - 1)];

Here, numberOfSections is the value you return from numberOfSectionsInTableView: method. And, numberOfRowsInLastSection is the value you return from numberOfRowsInSection: method for the last section in the table view.

This can be placed in a subclass or category to make it easy:

-(NSIndexPath*)indexPathForLastRow
{
    return [NSIndexPath indexPathForRow:[self numberOfRowsInSection:self.numberOfSections - 1] - 1 inSection:self.numberOfSections - 1];
}

In swift 3

let lastRowIndex = tableView.numberOfRows(inSection: tableView.numberOfSections-1)

if (indexPath.row == lastRowIndex - 1) {
     print("last row selected")
}

Probably someone will need the same for UICollectionView , so I updated Ryan Grimm 's answer for it:

NSInteger lastSectionIndex = [self.collectionView numberOfSections] - 1;
NSInteger lastItemIndex = [self.collectionView numberOfItemsInSection:lastSectionIndex] - 1;
NSIndexPath *pathToLastItem = [NSIndexPath indexPathForItem:lastItemIndex inSection:lastSectionIndex];

try this:

In cellForRowAtIndexPath

if(indexPath.row == myArray.count -1)

{
     myIndexPath = indexpath;
}

myIndexPath should be object of NSIndexPath

Here is an extension in Swift 4.x that takes into consideration that there may not be any rows, so it avoids out of range crashes.

import UIKit

extension UITableView {
    func lastIndexpath() -> IndexPath {
        let section = max(numberOfSections - 1, 0)
        let row = max(numberOfRows(inSection: section) - 1, 0)

        return IndexPath(row: row, section: section)
    }
}

Then call it from your viewcontroller with:

let lastIndexPath = tableView.lastIndexPath()

Most of the answers here, including the accepted answer, do not take into account the valid cases of a table view with zero sections, or a final section with zero rows.

The best way to represent those situations is using an index of NSNotFound , which is accepted by UIKit in methods such as scrollToRowAtIndexPath:atScrollPosition:animated: .

NSNotFound is a valid row index for scrolling to a section with zero rows.

I use the following method:

- (NSIndexPath *)bottomIndexPathOfTableView:(UITableView *)tableView
{
    NSInteger finalSection = NSNotFound;
    NSInteger finalRow = NSNotFound;

    NSInteger numberOfSections = [tableView numberOfSections];
    if (numberOfSections)
    {
        finalSection = numberOfSections - 1;
        NSInteger numberOfRows = [tableView numberOfRowsInSection:finalSection];
        if (numberOfRows)
        {
            finalRow = numberOfRows - 1;
        }
    }
    return numberOfSections ? [NSIndexPath indexPathForRow:finalRow inSection:finalSection] : nil;
}

It seems like all the solutions don't consider that the last section may have no rows at all . So here is a function which returns the last row in a last non-empty section:

Swift 3:

extension UITableViewDataSource {
    func lastIndexPath(_ tableView: UITableView) -> IndexPath? {
        guard let sections = self.numberOfSections?(in: tableView) else { return nil }
        for section in stride(from: sections-1, through: 0, by: -1) {
            let rows = self.tableView(tableView, numberOfRowsInSection: section)
            if rows > 0 {
                return IndexPath(row: rows - 1, section: section)
            }
        }
        return nil
    }
}

Example:

class ViewController: UIViewController {

    //...

    func scrollToLastRow() {
        if let indexPath = lastIndexPath(tableView) {
            tableView.scrollToRow(at: indexPath, at: .bottom, animated: true)
        }
    }
}

extension ViewController: UITableViewDataSource {
    //required data source methods
}

Swift 3 answer, with out of bounds checks. Implemented as a tableview extension

extension UITableView {

    var lastIndexPath: IndexPath? {

        let lastSectionIndex = numberOfSections - 1
        guard lastSectionIndex >= 0 else { return nil }

        let lastIndexInLastSection = numberOfRows(inSection: lastSectionIndex) - 1
        guard lastIndexInLastSection >= 0 else { return nil }

        return IndexPath(row: lastIndexInLastSection, section: lastSectionIndex)
    }
}

Try this code:

//   get number of section
let indexOfLastSection = self.yourTableView.numberOfSections - 1

// Then get the number of rows in the last section

if indexOfLastSection >= 0{
    let indexOfLastRow = self.yourTableView.numberOfRows(inSection: indexOfLastSection) - 1
    if indexOfLastRow >= 0{
        let pathToLastRow = IndexPath.init(row: indexOfLastRow, section: indexOfLastSection)
    }
}

My Swift 5 implementation ensures a valid IndexPath .

extension UITableView {
    
    /// Returns nil if the table view has no rows.
    func kjy_indexPathOfLastRow() -> IndexPath? {
        let sectionsCount = numberOfSections
        guard sectionsCount > 0 else {
            return nil
        }
        for section in (0..<sectionsCount).reversed() {
            let rowsCount = numberOfRows(inSection: section)
            if rowsCount > 0 {
                return IndexPath(row: rowsCount - 1, section: section)
            }
        }
        return nil
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM