[ios] UITableView의로드 끝을 감지하는 방법

로드가 완료되면 테이블의 오프셋을 변경하고 해당 오프셋은 테이블에로드 된 셀 수에 따라 다릅니다.

uitableview 로딩이 완료된 시점을 아는 것이 SDK에 있습니까? 대리인이나 데이터 소스 프로토콜에는 아무것도 보이지 않습니다.

보이는 셀만로드하기 때문에 데이터 소스 수를 사용할 수 없습니다.



답변

@RichX 답변으로 향상 :
또는 lastRow모두 가능합니다 . 따라서 코드는 다음과 같습니다.[tableView numberOfRowsInSection: 0] - 1((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject]).row

-(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];
    }
}

업데이트 :
글쎄, @htafoya의 의견이 맞습니다. 이 코드가 소스에서 모든 데이터로드의 끝을 감지하도록하려면 그렇지 않지만 원래 질문은 아닙니다. 이 코드는 보이는 모든 셀이 표시되는시기를 감지하기위한 것입니다. willDisplayCell:보다 부드러운 UI를 위해 여기에 사용됩니다 (단일 셀은 일반적으로 willDisplay:통화 후 빠르게 표시됨 ). 로 시도해 볼 수도 있습니다 tableView:didEndDisplayingCell:.


답변

스위프트 3 & 4 & 5 버전 :

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


답변

나는 항상이 매우 간단한 솔루션을 사용합니다 :

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


답변

나를 위해 일하는 것처럼 보이는 또 다른 옵션이 있습니다. viewForFooter 델리게이트 메소드에서 마지막 섹션인지 확인하고 코드를 추가하십시오. 이 방법은 willDisplayCell이 바닥 글이있는 경우 바닥 글을 고려하지 않는다는 것을 인식 한 후에 생각되었습니다.

- (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");
}

이 방법은 UITableView단순히 보이는 셀이 아니라 전체에 대한 최종로드를 찾고자 할 때 가장 효과적 입니다. 필요에 따라 보이는 셀만 원할 수 있으며,이 경우 folex의 대답 은 좋은 경로입니다.


답변

스위프트 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()
    }
}


답변

개인 API 사용 :

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

퍼블릭 API 사용 :

- (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;
}

더 나은 디자인은 보이는 셀을 세트에 추가하는 것입니다. 테이블이로드되었는지 확인해야하는 경우 대신이 세트 주위에 for 루프를 수행 할 수 있습니다.

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)
        }
    }
}


답변

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
        }
    }
}

기본 셀을 선택하기 전에 테이블로드가 완료되도록하기 위해 isLoadingTableView 변수가 필요했습니다. 이것을 포함하지 않으면 테이블을 스크롤 할 때마다 코드가 다시 호출됩니다.