UITableView iOS6底部的UIRefreshControl?

30

是否可以将UIRefreshControl添加到UITableView的底部?我想用它来加载更多数据。请问有什么建议吗?

8个回答

30

我认为这个问题不会有简单的解决方案。也许有人可以编写一个单独的库来实现这种行为,但一旦您在表视图中缓存数据,则会引起更多的复杂问题。

但我们可以分解这个问题,这可能有助于您实现所需的功能。我已经使用以下代码在应用程序中添加了更多的行:

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    float endScrolling = scrollView.contentOffset.y + scrollView.frame.size.height;
    if (endScrolling >= scrollView.contentSize.height)
    {
        NSLog(@"Scroll End Called");
        [self fetchMoreEntries];
    }
}

或者你可以像这样做:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if ((scrollView.contentOffset.y + scrollView.frame.size.height) >= scrollView.contentSize.height)
    {
        if (!self.isMoreData)
        {
            self.MoreData = YES;

            // call some method that handles more rows
        }
    }
}

你一定在很多问题中看到过我上面描述的方法,但肯定不是你所要求的。但是,在上述代码正在加载更多数据的过程中,您可以添加一个子视图并显示几张类似于UIRefreshControl提供的图片。将这些图片添加到子视图中,以作为进度展示,直到上述代码执行完毕。希望这可以帮助到你。

顺便说一句,我建议您不要这样做,除非您只是出于学习目的而进行这样的操作,否则这只会浪费您的时间,因为这个东西太小了。


12
以下答案适用于 Xcode 8 和 Swift 3。
首先声明:
var spinner = UIActivityIndicatorView()

比起在viewDidLoad方法中编写以下代码:
spinner = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge)
spinner.stopAnimating()
spinner.hidesWhenStopped = true
spinner.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 60)
tableView.tableFooterView = spinner

现在最终使用以下内容覆盖scrollViewDidEndDragging委托方法:

override func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        let offset = scrollView.contentOffset
        let bounds = scrollView.bounds
        let size = scrollView.contentSize
        let inset = scrollView.contentInset

        let y = offset.y + bounds.size.height - inset.bottom
        let h = size.height

        let reloadDistance = CGFloat(30.0)
        if y > h + reloadDistance {
            print("fetch more data")
            spinner.startAnimating()
        }
}

1
这是截至今年最正确的答案。我一直在使用CCBottomRefreshControl,直到我不得不将我的项目转换为Swift 3.0并且它开始随处崩溃。这是一个更好的解决方案。谢谢! - Paul Lehn
2
哥们,你真是救了我的一天。这是最好的 Swift 3 解决方案。 - Kautham Krishna
1
真的,这是最佳解决方案。 - Milan Kamilya
1
好的回答!只需要微调一下:你初始化了spinner = UIActivityIndicatorView(),然后在viewDidLoad()中你又用spinner = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge)进行了初始化。你可以消除其中一个。 - wildcat12
非常好的解决方案。请注意,在最新的Swift版本中,“override”语句是不必要的。 - Arik Segal

9
你可以使用UIView来自定义底部的refreshControl。创建一个UIView并将其添加到UITableView作为footerView。
UIView* footerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 50)];

[footerView setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"refreshImage.png"]]];

tableView.tableFooterView = footerView;

隐藏它:tableView.tableFooterView.hidden = YES;

实现UIScrollView代理 -

(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if ((scrollView.contentOffset.y + scrollView.frame.size.height) >= scrollView.contentSize.height)
    {
             tableView.tableFooterView.hidden = NO;
            // call method to add data to tableView
    }

}

在向tableView添加数据之前,先保存当前偏移量:CGPoint offset = tableView.contentOffset;

然后调用reloadData方法,并将之前保存的偏移量设置回tableView:[tableView setContentOffset:offset animated:NO];

这样你就可以感受到新添加的数据出现在底部了。


1
我正在我的iOS 7应用程序中使用它,它似乎有效。实际上,我将我的“tableFooterView”设置为“UIRefreshControl”视图。 - hunteros
1
抱歉,这是 UIActivityIndicatorView 而不是 UIRefreshControl - hunteros

8

最近我遇到了同样的问题,为UIScrollView类编写了一个分类。这里是CCBottomRefreshControl


具有ReactiveCocoa依赖,因此它是无用的。 - Roman Truba
1
对我来说完美地工作了。所有使用UIScrollViewDelegate方法的方法在性能方面都很麻烦。这种方法使用默认的UIRefreshControl元素,比我遇到的其他任何方法都要好得多。 - marcelosalloum
但是我遇到了一个问题。在数据加载完成后,我无法删除UIRefreshcontroller。[refreshController endRefreshing]没有任何作用。 - Shreesh Garg
@ShreeshGarg,请查看带有错误修复的新版本0.4.1。 - morbo
嘿Morbo,你能告诉我们如何减小刷新功能所需的高度尺寸吗?目前用户需要滚动表格很多次才能刷新数据。 - Shreesh Garg
@ShreeshGarg 我已经在UIRefreshControl类中添加了triggerVerticalOffset属性,因此现在您可以指定滚动偏移量以启动刷新功能。 - morbo

4

实际上,免费的Sensible TableView框架可以直接提供此功能。您只需指定批次号码,它就会自动获取数据,并将最后一个单元格显示为“加载更多”单元格。一旦您点击该单元格,它将自动加载下一批数据,以此类推。值得一看。


请在声明中说明您目前与该框架的关联(如果有的话),否则这可能会被视为垃圾邮件。 - ChrisF
1
没有任何关联!!只是一个狂热的粉丝! - Matt
我已经弄清楚了 - 但其他人可能不知道。 - ChrisF

2

对于UITableView,我建议采用以下方法:

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{    
    // if this is the last row that we have in local data
    // and we didn't reach the total count of rows from the server side
    if (count == indexPath.row+1 && count < total)
    {
        // .. fetch more rows and reload table when data comes
    }
}

我没有故意使用滚动视图方法,因为滚动视图很慢。当滚动视图滚动时,我们会请求更多的数据,刷新更多的行,而滚动视图还没有完成滚动,它仍在减速,并且在获取更多数据方面存在问题。


请简要解释一下 @Prcela - Pooja Srivastava

0

-1

在CocoaPods中使用CCBottomRefreshControl,

由于它是Objective语言的,您可以将pod文件添加到Swift项目中,然后运行它, 我已经这样做了,对我来说没有任何问题

希望能有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接