苹果开发 笔记(60)UIRefreshControl

refreshControl 是UITableViewController 里面一个属性,但是默认情况下是nil ,所以在使用其的时候需要创建,及其指定标题。一般情况下,我们有两种需求,一是下拉刷新,二是上拉滚动刷新新增多条数据。这两个需求用得比较频繁,下面来看看了两种需求的是怎样的运作情况。

1.下拉刷新

第一种方式是:下拉刷新的方式相对容易处理,监听UIRefreshControl 的UIControlEventValueChanged 事件后 当下拉的时候,该滚动的效果就会出来了。

@interface MainViewController ()
@property (nonatomic,strong) NSMutableArray *queryArray;
@property (nonatomic) NSInteger count;
@end
- (void)viewDidLoad
{
   [super viewDidLoad];
   self.count = 0;
   self.refreshControl  = [[UIRefreshControl alloc]init];
   self.refreshControl.attributedTitle  = [[NSAttributedString alloc] initWithString:@"刷新中..."];
   [self.refreshControl addTarget:self action:@selector(onRereshTableView) forControlEvents:UIControlEventValueChanged];
}

-(void) onRereshTableView
{
    //延迟执行
    [self performSelector:@selector(handlerData) withObject:nil afterDelay:2];
}

-(void) handlerData
{
    [self.refreshControl endRefreshing];
    self.count = 0;//默认不分页
    [self getNewData];
}

-(void) getNewData
{
  [_queryArray removeAllObjects];//清理数据
}

2.上拉刷新

第二种方式是 :(引用一个博客的文章来源做法),该方法主要在滚动条滚动完成后那里下手处理这个问题。也就是说当我们滚动到一定高度的时候,超出了原来的scrollView.contentSize.height的时候,原则理论上我们就执行刷新获取更多的内容方法。这里有一个细节的处理,就是递增数使用(统计你上拉刷新的次数)。我们知道,获取从服务器得到的数据是大部分来自数据库存款的。所以要进行分页查询的方式获取数据的方式处理这个问题。

分页最初的默认查询数据假设为10条,于是它下一次查询的开始就是从10开始查询 不包括10 。

伪代码如下: sql.limit = 10; sql.skip = self .count *sql.limit;

-(void) scrollViewDidScroll:(UIScrollView *)scrollView
{

    if (scrollView.contentOffset.y+scrollView.frame.size.height > scrollView.contentSize.height && scrollView.contentOffset.y >0)
    {
        //本身的内容高度
        CGSize size = self.tableView.contentSize;
        size.height+=115;
        self.tableView.contentSize = size;
       [ self performSelector:@selector(getMoreData) withObject:nil afterDelay:0];
    }
}

-(void)getMoreData 
{
  //不需要清理旧数据,让数组继续添加数据
  self.count++;
  //下面为处理分页查询的结果
  sql.limit = 10;//限定分页查询数
  sql.skip = self .count *sql.limit;//跳转分页
   ....
   ....
   [queryArray addObject:obj];
}

当上拉数据已经刷新完了,数据库已经没发查询到数据内容了,那么scrollViewDidScroll 和 getMoreData 或多或少有点漏洞和问题。所以这里还要完善一下。

我们使用这个组件主要的用于【下拉数据处理的逻辑】。下拉需要在UITableView的数据源清除干净再从远程获取最新时间表的数据。上拉需要在原来的数据源里面继续添加数据方式,并刷新UItableView 的内容高度来进行处理逻辑。一般情况下,我们需要增加一些额外的组件显示在下拉更新的过程。如UIButton 或者 UIActivityIndicatorView 的组件反馈在上拉的时候做出的UI反馈。

-(void) getNewData
{
  [_queryArray removeAllObjects];//需要清理旧数据再从后端数据库获取最新数据
   //请求网络情况
   [_queryArray addObject:obj];
   [self.tableView reloadData];
}

-(void)getMoreData 
{
    //不需要删除,继续添加数据
   [_queryArray addObject:obj];
   [self.tableView reloadData];
}

3. 疑惑点存在

如何理解下面的判断? 为什么 scrollView.contentOffset.y 在上拉的过程y是要求大于0 ? 这里我依旧感觉未解的地方。

  if (scrollView.contentOffset.y+scrollView.frame.size.height > scrollView.contentSize.height && scrollView.contentOffset.y >0)

scrollView.contentOffset.y 这个正好是往上拉刷新数据 所以这个值必须大于0.

(scrollView.contentOffset.y+scrollView.frame.size.height) 这个和 可以理解为
这里写图片描述

所以当继续往上拉的时候小框就是会大于scrollView.contentSize.height 。这样子就可以判断获取更多数据了。

你往上拉的时候, contentOffset.y 大于0

这里写图片描述

你往下拉的时候, contentOffset.y 小于0
这里写图片描述

你可以理解为大底的框是始终不动的,而是小框在在上下移动,框下移动,视角正好往上移动(contentOffset.y >0),框上移动的时候,视角刚好是往下移动。(contentOffset.y < 0)
可以想象一下。

4.弊端的存在设计

在开始测试的过程当中 配合 scrollViewDidScroll 和 self.count++; 这种方式存在一个严重弊端,就是无限制去拉伸的时候会不断执行- getMoreData 方法 自增器self.count 就很傻乎乎不断递增递增,这样子在分页查询的时候并不准确。接下来改成下面的方式。

NSInteger page = 0;

page  = self.count +1; 改成这种方式
sql.limit = 10; //默认请求分页数
sql.skip = page *sql.limit; //跳转页数获取数据
//请求后端获取数据成功后

才设置正确的当前页数
self.count = page; 

这样一来我们就可以解决到 self.count++ 的问题了。

接下来,我们还要继续处理scrollViewDidScroll 的逻辑问题

-(void) scrollViewDidScroll:(UIScrollView *)scrollView
{
   //处理滚动条高度的逻辑问题
   //不处理tableView的contentSize 的值改而直接
    if (scrollView.contentOffset.y+scrollView.frame.size.height > scrollView.contentSize.height && scrollView.contentOffset.y >0)
    {
    if(self.isRefresing) return;//刷新的时候屏蔽
    //处理下拉的动画显示
    ...
    .... 
 [ self performSelector:@selector(getMoreData) withObject:nil afterDelay:0];
 }
 }
-(void)getMoreData 
{
    //不需要删除,继续添加数据
    if(self.isRefresing) return ;

    //设置分页逻辑
     ...code
     // 
   self.isRefresing = YES;

   //成功后新增数据,数据刷新,将刷新状态变换NO,处理掉上拉动画
   [_queryArray addObject:obj];
   [self.tableView reloadData];
   self.isRefresing  = NO;
}

经过改动后,效果比第一种处理的方式会好一点。同样也要注意一点是下拉数据删除的时间,是在成功获取后数据才删除,而不是在第一个

-(void) getNewData
{
  [_queryArray removeAllObjects];//需要清理数据
  //从后端数据库获取最新数据
   [_queryArray addObject:obj];
   [self.tableView reloadData];
}

而是

-(void) getNewData
{ 
  //调用后端的请求 

  //从后端数据库获取最新数据回调后有数据才进行删除

   [_queryArray removeAllObjects];//需要清理数据
   for(NSObject *obj in array)
   {
     [_queryArray addObject:obj];
   }
   [self.tableView reloadData];
}

总体而言,第一次接触下拉和上拉刷新多多少少还是有很多问题。而在一些开源类当中,还有其他做法,比如采用KVO 监听滚动条contentoffset的变化,采用这种机制去设计刷新思路还是挺ok 的。

5.细节处理

当我们刷新的过多数据的时候,数组保存的东西越多,这个时候内存会紧张。在网易新闻客户端iphone 版本看到一个很小的细节。当分页数出现过多的时候,网易客户端不会主动给客户更新数据采取的方式 是让用户去选择处理按钮点击获取更多数据。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值