发布于 1970-01-01 08:00
  • 6 个回答
    • 您可以通过添加检查cellForRowAtIndexPath:方法中的位置来实现.这种方法易于理解和实现:

      - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
      {
          // Classic start method
          static NSString *cellIdentifier = @"MyCell";
          MyCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
          if (!cell)
          {
              cell = [[MyCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MainMenuCellIdentifier];
          }
      
          MyData *data = [self.dataArray objectAtIndex:indexPath.row];
          // Do your cell customisation
          // cell.titleLabel.text = data.title;
      
          BOOL lastItemReached = [data isEqual:[[self.dataArray] lastObject]]; 
          if (!lastItemReached && indexPath.row == [self.dataArray count] - 1)
          {
              [self launchReload];
          }
      }
      

      编辑:添加了对最后一项的检查以防止递归调用.您必须实现定义是否已到达最后一个项目的方法.

      EDIT2:解释了lastItemReached

      2023-02-14 05:14 回答
    • 迅速

      方法1:滚动到底部

      这是Swro版本的PedroRomão的答案.当用户停止滚动时,它会检查它是否已到达底部.

      func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
      
          // UITableView only moves in one direction, y axis
          let currentOffset = scrollView.contentOffset.y
          let maximumOffset = scrollView.contentSize.height - scrollView.frame.size.height
      
          // Change 10.0 to adjust the distance from bottom
          if maximumOffset - currentOffset <= 10.0 {
              self.loadMore()
          }
      }
      

      方法2:到达最后一行

      这是swinguX的答案的Swift版本.它检查用户是否已到达最后一行.

      func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
      
          // set up cell
          // ...
      
          // Check if the last row number is the same as the last current data element
          if indexPath.row == self.dataArray.count - 1 {
              self.loadMore()
          }
      
      }
      

      loadMore()方法示例

      我设置了这三个类变量来获取批量数据.

      // number of items to be fetched each time (i.e., database LIMIT)
      let itemsPerBatch = 50
      
      // Where to start fetching items (database OFFSET)
      var offset = 0
      
      // a flag for when all database items have already been loaded
      var reachedEndOfItems = false
      

      这是将更多项目从数据库加载到表视图中的功能.

      func loadMore() {
      
          // don't bother doing another db query if already have everything
          guard !self.reachedEndOfItems else {
              return
          }
      
          // query the db on a background thread
          DispatchQueue.global(qos: .background).async {
      
              // determine the range of data items to fetch
              var thisBatchOfItems: [MyObjects]?
              let start = self.offset
              let end = self.offset + self.itemsPerBatch
      
              // query the database
              do {
                  // SQLite.swift wrapper
                  thisBatchOfItems = try MyDataHelper.findRange(start..<end)
              } catch _ {
                  print("query failed")
              }
      
              // update UITableView with new batch of items on main thread after query finishes
              DispatchQueue.main.async {
      
                  if let newItems = thisBatchOfItems {
      
                      // append the new items to the data source for the table view
                      self.myObjectArray.appendContentsOf(newItems)
      
                      // reload the table view
                      self.tableView.reloadData()
      
                      // check if this was the last of the data
                      if newItems.count < self.itemsPerBatch {
                          self.reachedEndOfItems = true
                          print("reached end of data. Batch count: \(newItems.count)")
                      }
      
                      // reset the offset for the next data query
                      self.offset += self.itemsPerBatch
                  }
      
              }
          }
      }
      

      2023-02-14 05:14 回答
    • 最好使用willDisplayCell方法来检查是否将加载哪个单元格.一旦我们得到indexPath.row最后的电流,我们可以加载更多的单元格.这将在向下滚动时加载更多单元格.

       - (void)tableView:(UITableView *)tableView 
             willDisplayCell:(UITableViewCell *)cell    
             forRowAtIndexPath:(NSIndexPath *)indexPath
      {
          // check if indexPath.row is last row
          // Perform operation to load new Cell's.
      }
      

      2023-02-14 05:19 回答
    • - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
          NSInteger lastSectionIndex = [tableView numberOfSections] - 1;
          NSInteger lastRowIndex = [tableView numberOfRowsInSection:lastSectionIndex] - 1;
          if ((indexPath.section == lastSectionIndex) && (indexPath.row == lastRowIndex)) {
              // This is the last cell
              [self loadMore];
          }
      }
      

      如果您使用的是Core Data NSFetchedResultsController,则loadMore可能如下所示:

      // Load more
      - (void)loadMore {
          [self.fetchedResultsController.fetchRequest setFetchLimit:newFetchLimit];
          [NSFetchedResultsController deleteCacheWithName:@"cache name"];
          NSError *error;
          if (![self.fetchedResultsController performFetch:&error]) {
              // Update to handle the error appropriately.
              NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
          }
      
          [self.tableView reloadData];
      }
      

      2023-02-14 05:21 回答
    • 细节

      Xcode 10,Swift 4.2

      使用UIScrollView/UICollectionView/UITableView

      import UIKit
      
      protocol LoadMoreControlDelegate: class {
          func loadMoreControl(didStartAnimating loadMoreControl: LoadMoreControl)
          func loadMoreControl(didStopAnimating loadMoreControl: LoadMoreControl)
      }
      
      class LoadMoreControl {
      
          private let spacingFromLastCell: CGFloat
          private let indicatorHeight: CGFloat
          private weak var activityIndicatorView: UIActivityIndicatorView?
          private weak var scrollView: UIScrollView?
          weak var delegate: LoadMoreControlDelegate?
      
          private var defaultY: CGFloat {
              guard let height = scrollView?.contentSize.height else { return 0.0 }
              return height + spacingFromLastCell
          }
      
          init (scrollView: UIScrollView, spacingFromLastCell: CGFloat, indicatorHeight: CGFloat) {
              self.scrollView = scrollView
              self.spacingFromLastCell = spacingFromLastCell
              self.indicatorHeight = indicatorHeight
      
              let size:CGFloat = 40
              let frame = CGRect(x: (scrollView.frame.width-size)/2, y: scrollView.contentSize.height + spacingFromLastCell, width: size, height: size)
              let activityIndicatorView = UIActivityIndicatorView(frame: frame)
              activityIndicatorView.color = .black
              activityIndicatorView.hidesWhenStopped = true
              activityIndicatorView.autoresizingMask = [.flexibleLeftMargin, .flexibleRightMargin]
              scrollView.addSubview(activityIndicatorView)
              activityIndicatorView.isHidden = isHidden
              self.activityIndicatorView = activityIndicatorView
          }
      
          private var isHidden: Bool {
              guard let scrollView = scrollView else { return true }
              return scrollView.contentSize.height < scrollView.frame.size.height
          }
      
          func didScroll() {
              guard let scrollView = scrollView, let activityIndicatorView = activityIndicatorView else { return }
              let offsetY = scrollView.contentOffset.y
              activityIndicatorView.isHidden = isHidden
              if !activityIndicatorView.isHidden && offsetY >= 0 {
                  let contentDelta = scrollView.contentSize.height - scrollView.frame.size.height
                  let offsetDelta = offsetY - contentDelta
      
                  let newY = defaultY-offsetDelta
                  if newY < scrollView.frame.height {
                      activityIndicatorView.frame.origin.y = newY
                  } else {
                      if activityIndicatorView.frame.origin.y != defaultY {
                          activityIndicatorView.frame.origin.y = defaultY
                      }
                  }
      
                  if !activityIndicatorView.isAnimating {
                      if offsetY > contentDelta && offsetDelta >= indicatorHeight && !activityIndicatorView.isAnimating {
                          activityIndicatorView.startAnimating()
                          delegate?.loadMoreControl(didStartAnimating: self)
                      }
                  }
      
                  if scrollView.isDecelerating {
                      if activityIndicatorView.isAnimating && scrollView.contentInset.bottom == 0 {
                          UIView.animate(withDuration: 0.3) { [weak self, weak scrollView] in
                              if let bottom = self?.indicatorHeight {
                                  scrollView?.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: bottom, right: 0)
                              }
                          }
                      }
                  }
              }
          }
      
          func stop() {
              guard let scrollView = scrollView else { return }
              let contentDelta = scrollView.contentSize.height - scrollView.frame.size.height
              let offsetDelta = scrollView.contentOffset.y - contentDelta
              if offsetDelta >= 0 {
                  UIView.animate(withDuration: 0.3, animations: { [weak scrollView] in
                      scrollView?.contentInset = .zero
                  }) { [weak self] result in
                      if result { self?.endAnimating() }
                  }
              } else {
                  scrollView.contentInset = .zero
                  endAnimating()
              }
          }
      
          private func endAnimating() {
              activityIndicatorView?.stopAnimating()
              delegate?.loadMoreControl(didStopAnimating: self)
          }
      }
      

      用法

      loadMoreControl = LoadMoreControl(scrollView: tableView, spacingFromLastCell: 10, indicatorHeight: 60)
      loadMoreControl.delegate = self
      

      完整样本

      extension ViewController: LoadMoreControlDelegate {
          func loadMoreControl(didStartAnimating loadMoreControl: LoadMoreControl) {
              print("didStartAnimating")
          }
      
          func loadMoreControl(didStopAnimating loadMoreControl: LoadMoreControl) {
              print("didStopAnimating")
          }
      }
      
      extension ViewController: UITableViewDelegate {
          func scrollViewDidScroll(_ scrollView: UIScrollView) {
              loadMoreControl.didScroll()
          }
      }
      

      结果

      在此输入图像描述

      2023-02-14 05:23 回答
    • 下面的链接将提供示例代码.#Swift3

      用户需要拉出最后一个表格视图单元格,至少需要2个单元格才能从服务器获取更多数据.

      您还会发现Process cell也显示加载过程,如同最后一个单元格一样.

      它在Swift3中

      https://github.com/yogendrabagoriya/YBTableViewPullData

      2023-02-14 05:24 回答
    撰写答案
    今天,你开发时遇到什么问题呢?
    立即提问
    PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
    Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有