Cách phát hiện kết thúc tải UITableView


141

Tôi muốn thay đổi phần bù của bảng khi tải xong và phần bù đó phụ thuộc vào số lượng ô được tải trên bảng.

Có phải dù sao trên SDK cũng biết khi nào việc tải uitableview kết thúc? Tôi không thấy gì cả về đại biểu cũng như các giao thức nguồn dữ liệu.

Tôi không thể sử dụng số lượng nguồn dữ liệu do chỉ tải các ô hiển thị.


thử kết hợp số lượng nguồn dữ liệu và 'indexPathsForVisibleRows'
Swapnil Luktuke

1
Mở lại dựa trên thông tin thêm trong cờ: "Nó không trùng lặp. Nó hỏi về việc tải các ô hiển thị, không phải về kết thúc dữ liệu yêu cầu. Xem cập nhật cho câu trả lời được chấp nhận"
Kev

Giải pháp này hoạt động tốt cho tôi. Bạn kiểm tra nó stackoverflow.com/questions/1483581/
Mạnh

Câu trả lời:


224

Cải thiện để trả lời @RichX: lastRowcó thể là cả hai [tableView numberOfRowsInSection: 0] - 1hoặc ((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject]).row. Vì vậy, mã sẽ là:

-(void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if([indexPath row] == ((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject]).row){
        //end of loading
        //for example [activityIndicator stopAnimating];
    }
}

CẬP NHẬT: Vâng, nhận xét của @ htafoya là đúng. Nếu bạn muốn mã này phát hiện kết thúc tải tất cả dữ liệu từ nguồn, thì đó không phải là câu hỏi ban đầu. Mã này là để phát hiện khi tất cả các ô có nghĩa là hiển thị được hiển thị. willDisplayCell:được sử dụng ở đây để giao diện người dùng mượt mà hơn (một ô thường hiển thị nhanh sau khi willDisplay:gọi). Bạn cũng có thể thử nó với tableView:didEndDisplayingCell:.


Tốt hơn nhiều để biết khi tất cả các tế bào tải có thể nhìn thấy.
Eric

14
Tuy nhiên, điều này sẽ được gọi bất cứ khi nào người dùng cuộn để xem nhiều ô hơn.
htafoya

Vấn đề với điều này là nó không giải thích cho chế độ xem chân trang. Có thể không phải là một vấn đề cho hầu hết, nhưng nếu đó là bạn có thể áp dụng cùng một ý tưởng nhưng trong viewForFooterInSectionphương pháp.
Kyle Clegg

1
@KyleClegg patric.schenke đã đề cập đến một trong những lý do để bình luận cho câu trả lời của bạn. Ngoài ra, nếu chân trang không hiển thị ở cuối quá trình tải của ô thì sao?
folex

27
tableView: didEndDisplayingCell: thực sự được gọi khi xóa một ô khỏi chế độ xem, không phải khi kết xuất của nó trong chế độ xem hoàn tất để nó không hoạt động. Không phải là một tên phương pháp tốt. Phải đọc tài liệu.
Andrew Raphael

34

Phiên bản Swift 3 & 4 & 5:

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if let lastVisibleIndexPath = tableView.indexPathsForVisibleRows?.last {
        if indexPath == lastVisibleIndexPath {
            // do here...
        }
    }
}

1
phương pháp này được gọi khi chúng ta tải dữ liệu lần đầu tiên. Trong trường hợp của tôi chỉ có 4 ô có thể nhìn thấy. Tôi đã tải 8 hàng nhưng chức năng này vẫn được gọi. Điều tôi muốn là tải thêm dữ liệu khi người dùng cuộn xuống hàng cuối cùng
Muhammad Nayab

Xin chào Muhammad Nayab, có lẽ bạn có thể thay thế "if indexPath == lastVisible IndexPath" bằng "if indexPath.row == yourDataSource.count"
Daniele Ceglia 18/12/18

1
@DanieleCeglia Cảm ơn bạn đã chỉ ra điều này. if indexPath == lastVisible IndexPath && indexPath.row == yourDataSource.count - 1 cái này sẽ hoạt động với tôi. Chúc mừng !!!
Yogesh Patel

28

Tôi luôn sử dụng giải pháp rất đơn giản này:

-(void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if([indexPath row] == lastRow){
        //end of loading
        //for example [activityIndicator stopAnimating];
    }
}

Làm thế nào để phát hiện hàng cuối cùng? đó là vấn đề đối với tôi .. bạn có thể giải thích làm thế nào bạn có được điều đó trong điều kiện đó không.
Sameera Chathuranga

6
Hàng cuối cùng là [tableView numberOfRowsInSection: 0] - 1. Bạn phải thay thế 0bằng giá trị cần thiết. Nhưng đó không phải là vấn đề. Vấn đề là tải UITableView chỉ hiển thị. Tuy nhiên ((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject]).rowgiải quyết vấn đề.
folex

1
Nếu chúng tôi đang tìm kiếm sự hoàn thành tuyệt đối thì sẽ không tốt nhất để sử dụng - (void) tableView: (UITableView *) tableView didEndDisplayingCell: (UITableViewCell *) cell forRowAtIndexPath: (NS IndexPath *) indexPath?
morcutt

10

Đây là một lựa chọn khác có vẻ hiệu quả với tôi. Trong phương thức ủy nhiệm của viewForFooter, hãy kiểm tra xem đó có phải là phần cuối cùng không và thêm mã của bạn vào đó. Cách tiếp cận này xuất hiện trong tâm trí sau khi nhận ra rằng willDisplayCell không tính đến phần chân trang nếu bạn có chúng.

- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section 
{
  // Perform some final layout updates
  if (section == ([tableView numberOfSections] - 1)) {
    [self tableViewWillFinishLoading:tableView];
  }

  // Return nil, or whatever view you were going to return for the footer
  return nil;
}

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
  // Return 0, or the height for your footer view
  return 0.0;
}

- (void)tableViewWillFinishLoading:(UITableView *)tableView
{
  NSLog(@"finished loading");
}

Tôi thấy cách tiếp cận này hoạt động tốt nhất nếu bạn đang tìm kiếm tải cuối cùng cho toàn bộ UITableView, và không chỉ đơn giản là các ô có thể nhìn thấy. Tùy thuộc vào nhu cầu của bạn, bạn có thể chỉ muốn các ô hiển thị, trong trường hợp đó , câu trả lời của folex là một lộ trình tốt.


Trở về niltừ tableView:viewForFooterInSection:mớ hỗn độn với bố cục của tôi trong iOS 7 bằng Giao diện tự động.
ma11hew28

Hấp dẫn. Điều gì nếu bạn đặt nó thành một khung có chiều cao và chiều rộng 0? return CGRectMake(0,0,0,0);
Kyle Clegg

Tôi đã thử điều đó và thậm chí thiết lập self.tableView.sectionFooterHeight = 0. Dù bằng cách nào, nó dường như chèn một chế độ xem chân trang với chiều cao khoảng 10. Tôi cá là tôi có thể khắc phục điều này bằng cách thêm một ràng buộc 0 chiều cao cho chế độ xem tôi quay lại. Dù sao, tôi tốt vì tôi thực sự muốn tìm ra cách khởi động UITableView trên ô cuối cùng nhưng đã thấy điều này trước tiên.
ma11hew28

1
@MattDiPasquale nếu bạn triển khai viewForFooterInSection, bạn cũng phải triển khai heightForFooterInSection. Nó phải trả về 0 cho các phần có chân trang không. Điều này cũng là trong các tài liệu chính thức bây giờ.
patric.schenke 17/12/13

viewForFooterInSection sẽ không được gọi nếu bạn đặt heightForFooterInSection thành 0
Oded Harth

10

Giải pháp Swift 2:

// willDisplay function
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    let lastRowIndex = tableView.numberOfRowsInSection(0)
    if indexPath.row == lastRowIndex - 1 {
        fetchNewDataFromServer()
    }
}

// data fetcher function
func fetchNewDataFromServer() {
    if(!loading && !allDataFetched) {
        // call beginUpdates before multiple rows insert operation
        tableView.beginUpdates()
        // for loop
        // insertRowsAtIndexPaths
        tableView.endUpdates()
    }
}

9

Sử dụng API riêng:

@objc func tableViewDidFinishReload(_ tableView: UITableView) {
    print(#function)
    cellsAreLoaded = true
}

Sử dụng API công khai:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // cancel the perform request if there is another section
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(tableViewDidLoadRows:) object:tableView];

    // create a perform request to call the didLoadRows method on the next event loop.
    [self performSelector:@selector(tableViewDidLoadRows:) withObject:tableView afterDelay:0];

    return [self.myDataSource numberOfRowsInSection:section];
}

// called after the rows in the last section is loaded
-(void)tableViewDidLoadRows:(UITableView*)tableView{
    self.cellsAreLoaded = YES;
}

Một thiết kế tốt hơn có thể là thêm các ô hiển thị vào một tập hợp, sau đó khi bạn cần kiểm tra xem bảng đã được tải chưa, thay vào đó bạn có thể thực hiện một vòng lặp for xung quanh tập hợp này, vd

var visibleCells = Set<UITableViewCell>()

override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    visibleCells.insert(cell)
}

override func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    visibleCells.remove(cell)
}

// example property you want to show on a cell that you only want to update the cell after the table is loaded. cellForRow also calls configure too for the initial state.
var count = 5 {
    didSet {
        for cell in visibleCells {
            configureCell(cell)
        }
    }
}

Giải pháp tốt hơn nhiều so với những người khác. Nó không yêu cầu tải lại bảngView. Điều đó rất đơn giản và viewDidLoadRows: không được gọi mỗi khi ô cuối cùng được tải.
Matt Hudson

đây là giải pháp tốt nhất cho đến nay, vì các giải pháp khác không tính đến nhiều phần
Justicepenny

Tôi xin lỗi vì nhận xét lén lút, nhưng chính xác thì đây là 'ma thuật' như thế nào? Gọi ra một phương pháp khác từ đại biểu. Tôi không hiểu
Lukas Petr

@LukasPetr hãy xem việc hủy bỏ và afterDelay. Các lệnh này cho phép hủy cuộc gọi phương thức cho mọi phần ngoại trừ phần cuối cùng, đó là khi bảng đã tải xong.
malhal

@malhal oh, được thôi. Đó là một chút thông minh hơn tôi nghĩ thoạt nhìn.
Lukas Petr

8

Đối với phiên bản trả lời được chọn trong Swift 3:

var isLoadingTableView = true

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if tableData.count > 0 && isLoadingTableView {
        if let indexPathsForVisibleRows = tableView.indexPathsForVisibleRows, let lastIndexPath = indexPathsForVisibleRows.last, lastIndexPath.row == indexPath.row {
            isLoadingTableView = false
            //do something after table is done loading
        }
    }
}

Tôi cần biến isLoadingTableView vì tôi muốn đảm bảo bảng được tải xong trước khi tôi thực hiện lựa chọn ô mặc định. Nếu bạn không bao gồm điều này thì mỗi khi bạn cuộn bảng, nó sẽ gọi lại mã của bạn.


6

Cách tiếp cận tốt nhất mà tôi biết là câu trả lời của Eric tại: Nhận thông báo khi UITableView kết thúc yêu cầu dữ liệu?

Cập nhật: Để làm cho nó hoạt động, tôi phải thực hiện các cuộc gọi này -tableView:cellForRowAtIndexPath:

[tableView beginUpdates];
[tableView endUpdates];

Đối với giá trị của nó, tôi đã sử dụng phương pháp rất đơn giản này trên tất cả các dự án của mình trong nhiều tháng và nó hoạt động hoàn hảo.
Eric MORAND

3

Để biết khi nào chế độ xem bảng hoàn tất tải nội dung của nó, trước tiên chúng ta cần có hiểu biết cơ bản về cách các chế độ xem được hiển thị trên màn hình.

Trong vòng đời của một ứng dụng, có 4 thời điểm chính:

  1. Ứng dụng nhận được một sự kiện (chạm, hẹn giờ, gửi đi, v.v.)
  2. Ứng dụng xử lý sự kiện (nó sửa đổi một ràng buộc, bắt đầu một hình động, thay đổi nền, v.v.)
  3. Ứng dụng tính toán phân cấp chế độ xem mới
  4. Ứng dụng hiển thị phân cấp chế độ xem và hiển thị nó

2 và 3 lần hoàn toàn tách biệt. Tại sao ? Vì lý do hiệu suất, chúng tôi không muốn thực hiện tất cả các tính toán của thời điểm 3 mỗi lần thực hiện sửa đổi.

Vì vậy, tôi nghĩ rằng bạn đang phải đối mặt với một trường hợp như thế này:

tableView.reloadData()
tableView.visibleCells.count // wrong count oO

Có chuyện gì ở đây vậy?

Giống như bất kỳ chế độ xem nào, chế độ xem bảng tải lại nội dung của nó một cách lười biếng. Trên thực tế, nếu bạn gọi reloadDatanhiều lần, nó sẽ không tạo ra vấn đề về hiệu suất. Chế độ xem bảng chỉ tính toán lại kích thước nội dung của nó dựa trên việc triển khai ủy nhiệm của nó và đợi thời điểm 3 để tải các ô của nó. Thời gian này được gọi là vượt qua bố trí.

Được rồi, làm thế nào để vào được pass layout?

Trong quá trình bố trí, ứng dụng sẽ tính toán tất cả các khung của hệ thống phân cấp chế độ xem. Để tham gia, bạn có thể ghi đè các phương thức chuyên dụng layoutSubviews, updateLayoutConstraintsvv trong một UIViewvà các phương thức tương đương trong lớp con của trình điều khiển xem.

Đó chính xác là những gì một chế độ xem bảng làm. Nó ghi đè layoutSubviewsvà dựa trên việc triển khai ủy nhiệm của bạn thêm hoặc xóa các ô. Nó gọi cellForRowngay trước khi thêm và đặt một ô mới, willDisplayngay sau đó. Nếu bạn đã gọi reloadDatahoặc chỉ thêm chế độ xem bảng vào cấu trúc phân cấp, chế độ xem bảng sẽ thêm nhiều ô cần thiết để điền vào khung của nó tại thời điểm quan trọng này.

Được rồi, nhưng bây giờ, làm thế nào để biết khi nào một chế độ xem bảng đã tải lại nội dung của nó?

Bây giờ chúng ta có thể viết lại câu hỏi này: làm thế nào để biết khi nào một chế độ xem bảng đã hoàn thành việc đưa ra các bản xem xét của nó?

Cách dễ nhất là vào bố cục của chế độ xem bảng:

class MyTableView: UITableView {
    func layoutSubviews() {
        super.layoutSubviews()
        // the displayed cells are loaded
    }
}

Lưu ý rằng phương thức này được gọi nhiều lần trong vòng đời của chế độ xem bảng. Do cuộn và hành vi dequeue của chế độ xem bảng, các ô được sửa đổi, loại bỏ và thêm thường xuyên. Nhưng nó hoạt động, ngay sau khi super.layoutSubviews(), các tế bào được tải. Giải pháp này tương đương với việc chờ willDisplaysự kiện của đường dẫn chỉ mục cuối cùng. Sự kiện này được gọi trong quá trình thực hiện layoutSubviewschế độ xem bảng cho mỗi ô được thêm vào.

Một cách khác là được gọi khi ứng dụng hoàn thành việc vượt qua bố cục.

Như được mô tả trong tài liệu , bạn có thể sử dụng một tùy chọn UIView.animate(withDuration:completion):

tableView.reloadData()
UIView.animate(withDuration: 0) {
    // layout done
}

Giải pháp này hoạt động nhưng màn hình sẽ làm mới một lần giữa thời gian bố trí được thực hiện và thời gian khối được gọi. Điều này tương đương với DispatchMain.asyncgiải pháp nhưng được chỉ định.

Ngoài ra, tôi muốn buộc bố cục của chế độ xem bảng

Có một phương pháp chuyên dụng để buộc bất kỳ chế độ xem nào tính toán ngay các khung nhìn phụ của nó layoutIfNeeded:

tableView.reloadData()
table.layoutIfNeeded()
// layout done

Tuy nhiên, hãy cẩn thận, làm như vậy sẽ loại bỏ tải lười biếng được sử dụng bởi hệ thống. Gọi các phương thức đó nhiều lần có thể tạo ra các vấn đề hiệu suất. Đảm bảo rằng chúng sẽ không được gọi trước khi khung của chế độ xem bảng được tính, nếu không, chế độ xem bảng sẽ được tải lại và bạn sẽ không được thông báo.


Tôi nghĩ rằng không có giải pháp hoàn hảo. Các lớp học phân lớp có thể dẫn đến các trubles. Một đường chuyền bố trí bắt đầu từ trên xuống và đi xuống dưới để không dễ dàng nhận được thông báo khi tất cả bố cục được thực hiện. Và layoutIfNeeded()có thể tạo ra các vấn đề về hiệu suất, v.v. Nhưng biết những lựa chọn đó, bạn sẽ có thể suy nghĩ ở một giải pháp thay thế phù hợp với nhu cầu của bạn.


1

Đây là cách bạn làm điều đó trong Swift 3:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    if indexPath.row == 0 {
        // perform your logic here, for the first row in the table
    }

    // ....
}

1

đây là cách tôi làm trong Swift 3

let threshold: CGFloat = 76.0 // threshold from bottom of tableView

internal func scrollViewDidScroll(_ scrollView: UIScrollView) {

    let contentOffset = scrollView.contentOffset.y
    let maximumOffset = scrollView.contentSize.height - scrollView.frame.size.height;

    if  (!isLoadingMore) &&  (maximumOffset - contentOffset <= threshold) {
        self.loadVideosList()
    }
}

1

Đây là những gì tôi sẽ làm.

  1. Trong lớp cơ sở của bạn (có thể là rootVC BaseVc, v.v.),

    A. Viết Giao thức để gửi cuộc gọi lại "DidFinishReloading".

    @protocol ReloadComplition <NSObject>
    @required
    - (void)didEndReloading:(UITableView *)tableView;
    @end

    B. Viết một phương thức chung để tải lại chế độ xem bảng.

    -(void)reloadTableView:(UITableView *)tableView withOwner:(UIViewController *)aViewController;
  2. Trong triển khai phương thức lớp cơ sở, gọi reloadData theo sau là ủy nhiệmMethod với độ trễ.

    -(void)reloadTableView:(UITableView *)tableView withOwner:(UIViewController *)aViewController{
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            [tableView reloadData];
            if(aViewController && [aViewController respondsToSelector:@selector(didEndReloading:)]){
                [aViewController performSelector:@selector(didEndReloading:) withObject:tableView afterDelay:0];
            }
        }];
    }
  3. Xác nhận với giao thức hoàn thành tải lại trong tất cả các bộ điều khiển xem nơi bạn cần gọi lại.

    -(void)didEndReloading:(UITableView *)tableView{
        //do your stuff.
    }

Tham khảo: https://discussions.apple.com/thread/2598339?start=0&tstart=0


0

@ Scratchex trả lời là đúng.

Nhưng nó sẽ thất bại nếu bảngView có nhiều phần được hiển thị cùng một lúc.

-(void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
   if([indexPath isEqual:((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject])]){
    //end of loading

 }
}

0

Trong Swift bạn có thể làm một cái gì đó như thế này. Điều kiện sau sẽ đúng mỗi khi bạn đến cuối bảngView

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
        if indexPath.row+1 == postArray.count {
            println("came to last row")
        }
}


0

Nếu bạn có nhiều phần, đây là cách lấy hàng cuối cùng trong phần cuối (Swift 3):

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if let visibleRows = tableView.indexPathsForVisibleRows, let lastRow = visibleRows.last?.row, let lastSection = visibleRows.map({$0.section}).last {
        if indexPath.row == lastRow && indexPath.section == lastSection {
            // Finished loading visible rows

        }
    }
}

0

Vô tình tôi đã va vào giải pháp này:

tableView.tableFooterView = UIView()
tableViewHeight.constant = tableView.contentSize.height

Bạn cần đặt footerView trước khi lấy contentSize, ví dụ như trong viewDidLoad. Btw. thiết lập footeView cho phép bạn xóa các dấu phân cách "không sử dụng"


-1

Bạn đang tìm kiếm tổng số mục sẽ được hiển thị trong bảng hoặc tổng số mục hiện có thể nhìn thấy? Dù bằng cách nào .. Tôi tin rằng phương thức 'viewDidLoad' thực thi sau khi tất cả các phương thức nguồn dữ liệu được gọi. Tuy nhiên, điều này sẽ chỉ hoạt động trong lần tải dữ liệu đầu tiên (nếu bạn đang sử dụng một ViewContoder cấp phát duy nhất).


-1

Tôi đang sao chép mã của Andrew và mở rộng nó sang tài khoản cho trường hợp bạn chỉ có 1 hàng trong bảng. Nó làm việc cho đến nay đối với tôi!

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
// detect when all visible cells have been loaded and displayed
// NOTE: iOS7 workaround used - see: http://stackoverflow.com/questions/4163579/how-to-detect-the-end-of-loading-of-uitableview?lq=1
NSArray *visibleRows = [tableView indexPathsForVisibleRows];
NSIndexPath *lastVisibleCellIndexPath = [visibleRows lastObject];
BOOL isPreviousCallForPreviousCell = self.previousDisplayedIndexPath.row + 1 == lastVisibleCellIndexPath.row;
BOOL isLastCell = [indexPath isEqual:lastVisibleCellIndexPath];
BOOL isFinishedLoadingTableView = isLastCell && ([tableView numberOfRowsInSection:0] == 1 || isPreviousCallForPreviousCell);

self.previousDisplayedIndexPath = indexPath;

if (isFinishedLoadingTableView) {
    [self hideSpinner];
}
}

LƯU Ý: Tôi chỉ sử dụng 1 phần từ mã của Andrew, vì vậy hãy ghi nhớ điều đó ..


Chào mừng bạn đến với SO @ jpage4500. Tôi đã chỉnh sửa câu trả lời của bạn để xóa nội dung về điểm đại diện thấp và câu hỏi khó. Mở rộng câu trả lời của người dùng khác là một câu trả lời hoàn toàn hợp lệ, vì vậy bạn có thể giảm bớt sự lộn xộn bằng cách bỏ qua những thứ đó. Thật tốt khi bạn đã cho Andrew tín dụng, vì vậy vẫn ở lại.
skrrgwasme 23/07/14

-3

Trong iOS7.0x, giải pháp hơi khác một chút. Đây là những gì tôi đã đưa ra.

    - (void)tableView:(UITableView *)tableView 
      willDisplayCell:(UITableViewCell *)cell 
    forRowAtIndexPath:(NSIndexPath *)indexPath
{
    BOOL isFinishedLoadingTableView = [self isFinishedLoadingTableView:tableView  
                                                             indexPath:indexPath];
    if (isFinishedLoadingTableView) {
        NSLog(@"end loading");
    }
}

- (BOOL)isFinishedLoadingTableView:(UITableView *)tableView 
                         indexPath:(NSIndexPath *)indexPath
{
    // The reason we cannot just look for the last row is because 
    // in iOS7.0x the last row is updated before
    // looping through all the visible rows in ascending order 
    // including the last row again. Strange but true.
    NSArray * visibleRows = [tableView indexPathsForVisibleRows];   // did verify sorted ascending via logging
    NSIndexPath *lastVisibleCellIndexPath = [visibleRows lastObject];
    // For tableviews with multiple sections this will be more complicated.
    BOOL isPreviousCallForPreviousCell = 
             self.previousDisplayedIndexPath.row + 1 == lastVisibleCellIndexPath.row;
    BOOL isLastCell = [indexPath isEqual:lastVisibleCellIndexPath];
    BOOL isFinishedLoadingTableView = isLastCell && isPreviousCallForPreviousCell;
    self.previousDisplayedIndexPath = indexPath;
    return isFinishedLoadingTableView;
}

-3

Mục tiêu C

[self.tableView reloadData];
[self.tableView performBatchUpdates:^{}
                              completion:^(BOOL finished) {
                                  /// table-view finished reload
                              }];

Nhanh

self.tableView?.reloadData()
self.tableView?.performBatchUpdates({ () -> Void in

                            }, completion: { (Bool finished) -> Void in
                                /// table-view finished reload
                            })

1
Phương pháp này chỉ có sẵn UICollectionViewtheo như tôi hiểu.
Tuyệt vời-o

Vâng, bạn đúng. BeginUpdates của UITableView tương đương với PerformanceBatchUpdates: hoàn thành của UICollectionView. stackoverflow.com/a/25128583/988169
pkc456

Vì vậy, đưa ra một câu trả lời thích hợp và hợp lệ cho câu hỏi.
G.Abhisek
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.