在UICollectionView的底部加载额外的单元格

我正尝试自动获取并加载下一页的单元格,当用户滚动到UICollectionView的底部。

我能够通过在UICollectoinView页脚中添加一个UIButtonUICollectoinView 。 当用户滚动到页脚并触摸button时,新的单元格被正确添加。 可以再次触摸页脚中的UIButton来添加更多的页面。

我试图自动化,所以当用户滚动到底部时,自动调用添加新单元格的正确方法:

 - (UICollectionReuseableView *)collectionView: (UICollectionView *)collectionView viewForSupplementaryElementOfKind: (NSString *)kind atIndexPath: (NSIndexPath *) indexPath { // code for headerView // ... // code for footerView MySupplementalFooter *footerView = nil; if ( [kind isEqual:UICollectionElementKindSectionFooter] ) { footerView = [self.collectionView dequeueReuseableSupplemntaryViewOfKind:kind withReuseIdentifier:@"FooterId" forIndexPath:indexPath]; if (LoadMoreIsEnabled) { footerView.loadMoreFooterButton.setHidden:NO]; [self loadMoreFooterButtonAction]; // calls the method to add cells to the dictionary for cv } else { footerView.loadMoreFooterButton setHidden:YES]; } return footerView; } } 

loadMoreFooterButtonAction方法被调用,但整个UICollectionView空白。 刷新UICollectionView不会使其恢复。

我假设你正在尝试从桌面网页上进行“无限滚动”的操作,当用户进入页面底部时,你会加载更多的内容。 在iOS上,这不是一个非常常用的devise。 通常情况下,开发人员将使用绝对总数的条目初始化他们的UITableView或UICollectionView。 如果他们需要通过networking传输数据,他们会根据需要asynchronous加载数据(当单元格或视图出现在屏幕上时),直到内容加载后才显示某种临时内容,如带有微调框的空白视图。

也就是说,如果你想以更像桌面Web应用程序的方式进行无限滚动,则应该实现UIScrollViewDelegate协议(或UICollectionViewDelegate,这是一个超集),并侦听scrollViewDidScroll: callback。 在该callback中,遍历UICollectionView的indexPathsForVisibleItems并检查是否有任何索引path映射到集合中的“last”项,这表示用户已滚动到结尾。 在这一点上,调用你的逻辑来加载更多的东西。

在IOS8中有一个UICollectionViewDelegate方法willDisplayCell

 func collectionView(collectionView: UICollectionView, willDisplayCell cell: UICollectionViewCell, forItemAtIndexPath indexPath: NSIndexPath) { if indexPath.item == (data.count-1) { loadData() } } 

在表格视图中,您应该在willDisplayCell()方法中加载更多的数据。 collections,没有这样一个对手。 但是,你可以这样做。 希望能帮助到你。

 - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { // Other code here ... if (indexPath.item == [self.photos count] - 1) { [self loadPhotos]; } return cell; } - (void)loadPhotos { [self showLoadingIndicator]; self.operation = [client HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) { [self hideLoadingIndicator]; // Get data NSArray *photosData = responseObject[@"data"]; NSInteger numberOfResults = [photosData count]; NSInteger totalCount = [self.photos count]; if (numberOfResults > 0) { NSMutableArray *indexPaths = [NSMutableArray new]; for (NSInteger i = 0; i < numberOfResults; i++) { Photo *photo = [Photo new]; photo._id = [photoData[@"id"] integerValue]; photo.url = photoData[@"url"]; [self.photos addObject:photo]; [indexPaths addObject:[NSIndexPath indexPathForRow:totalCount + i inSection:0]]; } [self.collectionView performBatchUpdates:^{ [self.collectionView insertItemsAtIndexPaths:indexPaths]; } completion:nil]; } } failure:^(AFHTTPRequestOperation *operation, NSError *error) { [self hideLoadingIndicator]; // Handle error here }]; [self.operation start]; } 

我知道这是一个老问题,但我会为未来的答案提供一个解决scheme。 通常当我在UITableView上进行无限滚动时,我会检查tableView的滚动视图的边界是否与tableFooterView的矩形相交。 页脚视图在UICollectionViews中稍微复杂一点,所以我在collectionView的末尾创build了一个矩形,看看它是否与scrollView边界相交,如果是,则加载更多的项目。 我也检查过,我们至less有一些东西在表中,所以我不会试图在表实例化的时候加载更多的东西。

注意:在这种情况下,您的more方法将更新您的collectionView数据源,追加新的项目。 你的numberOfItems / sections方法应该反映新的计数。

 - (void)scrollViewDidScroll:(UIScrollView *)scrollView { if (CGRectIntersectsRect(scrollView.bounds, CGRectMake(0, self.collectionView.contentSize.height, CGRectGetWidth(self.view.frame), 40)) && self.collectionView.contentSize.height > 0) { [self more]; } } 

你也可以使用collectionView(_:prefetchItemsAt:)教程1和2 。

我遇到了困难转换@ sukhrob的答案迅速为我的项目,所以这里是他在Swift 3的代码,方便复制和粘贴。

 func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { // Other code here ... if indexPath.item == photos.count() - 1 { loadPhotos() } return cell } func loadPhotos() { showLoadingIndicator() operation = client.httpRequestOperation(with: request, success: {(_ operation: AFHTTPRequestOperation, _ responseObject: Any) -> Void in self.hideLoadingIndicator() // Get data let photosData: [Any] = responseObject["data"] let numberOfResults: Int = photosData.count let totalCount: Int = photos.count() if numberOfResults > 0 { var indexPaths = [Any]() var i = 0 while i < numberOfResults { let photo = Photo() photo.id = CInt(photoData["id"]) photo.url = photoData["url"] photos.append(photo) indexPaths.append(IndexPath(row: totalCount + i, section: 0)) i } i += 1 collectionView?.performBatchUpdates({() -> Void in collectionView?.insertItems(at: indexPaths as? [IndexPath] ?? [IndexPath]()) }) { _ in } } }, failure: {(_ operation: AFHTTPRequestOperation, _ error: Error?) -> Void in self.hideLoadingIndicator() // Handle error here }) operation.start()