百思不得姐数据刷新数据部分(七)

一 刷新功能图和内部计算原理图

1 刷新功能图:

这里写图片描述

2 内部计算原理图

这里写图片描述

二 解析步骤

1 分析整个精华模块
2 真实数据请求部分
3 模型
4 先添加尾部刷新控件
5 再添加头部刷新控件
6 处理刷新业务逻辑
7 知识点补充

三 分析模块

1 从一个完整的app中可以看出,在精华模块中处于全部标题的部分数据包括了其它几部分的数据,内部有视频;声音;图片和段子,所以我们只需要将”全部”做好,就能很快的搞定其它模块了.

四 真实数据请求

1 大致步骤:
—-> 1 查看百思不得姐该部分的接口文档,获取URL.
—-> 2 查看接口文档中哪些是需要的请求参数(在百思不得姐的接口文档中:后面表明了ture是必须要的请求参数)
—-> 3 查看接口文档,请求方式是什么?这里是GET请求.
—-> 4 zing共请求数据分三大步骤:1> 创建会话管理者 2> 设置请求参数 3> 发送请求.
2 需要导入的框架
#import <AFNetworking.h>

#import <MJExtension/MJExtension.h>

#import <SVProgressHUD.h>
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
3 代码部分:加载更多数据;加载最新数据
—> 3.1 加载更多帖子
#pragma mark - 加载更多的帖子数
- (void)setUpMoreTopics
{
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        //设置请求参数
        NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
        //包装请求参数
        parameters[@"a"] = @"list";
        parameters[@"c"] = @"data";
        parameters[@"type"] = @"31";
        parameters[@"maxtime"] = self.maxtime;
        //发送请求
        [[AFHTTPSessionManager manager] GET:XFJ_requestURL parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            //取出info中的maxtime
            self.maxtime = responseObject[@"info"][@"maxtime"];
            //字典数组转模型数组(装入可变数组中)
            NSArray *arrayTopics = [XFJItem mj_objectArrayWithKeyValuesArray:responseObject[@"list"]];
            //将模型添加到装数组的模型中
            [self.item addObjectsFromArray:arrayTopics];
            //写入plist文件
            [responseObject writeToFile:@"/Users/xiaofeng/Desktop/New.plist" atomically:YES];
            //刷新tableView
            [self.tableView reloadData];
            //尾部结束刷新
            [self footerEndRefresh];
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            //尾部刷新数据失败也需要调用
            [self footerEndRefresh];
            //如果用户直接取消任务,来到failure中不需要提醒信息
            if (error.code == NSURLErrorCancelled) {
                return ;
            }
            //提醒用户刷新失败
            [SVProgressHUD showErrorWithStatus:@"网络繁忙,请稍后再试..."];
        }];
    });
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
—-> 3.2 加载最新的数据
#pragma mark - 加载最新的帖子数
- (void)setLoadNews
{
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        //设置请求参数
        NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
        //包装请求体
        parameters[@"a"] = @"list";
        parameters[@"c"] = @"data";
        parameters[@"type"] = @"31";
        //发送请求
        [[AFHTTPSessionManager manager] GET:XFJ_requestURL parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            //取出info中的maxtime
            self.maxtime = responseObject[@"info"][@"maxtime"];
            //字典数组转模型数组
            self.item = [XFJItem mj_objectArrayWithKeyValuesArray:responseObject[@"list"]];
            [responseObject writeToFile:@"/Users/xiaofeng/Desktop/New1.plist" atomically:YES];
            //刷新
            [self.tableView reloadData];
            //结束刷新
            [self headerEndRefresh];
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            //刷新失败了也需要结束
            [self headerEndRefresh];
            //如果用户直接取消任务,来到failure中不需要提醒信息
            if (error.code == NSURLErrorCancelled) {
                return ;
            }
            //提醒用户刷新失败
            [SVProgressHUD showErrorWithStatus:@"网络繁忙,请稍后再试..."];
        }];
    });
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

五 模型

1 模型中的数据部分选择所有模块的公共部分作为属性
2 代码:
/**
 *  踩(hate)
 */
@property (nonatomic, assign) NSInteger cai;
/**
 *  顶(love)
 */
@property (nonatomic, assign) NSInteger love;
/**
 *  帖子描述
 */
@property (nonatomic, strong) NSString *text;
/**
 *  发帖时间
 */
@property (nonatomic, strong) NSString *passtime;
/**
 *  用户名
 */
@property (nonatomic, strong) NSString *name;
/**
 *  转发
 */
@property (nonatomic, assign) NSInteger repost;
/**
 *  转发数
 */
@property (nonatomic, assign) NSInteger comment;
/**
 *  头像
 */
@property (nonatomic, strong) NSString *profile_image;
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

六 添加尾部刷新控件

1 这里采用UILabel作为刷新的控件(也可以采用UIView)
2 注意刷新控件的添加位置(可以通过内部计算原理图来添加)
3 代码:
#pragma mark - 创建刷新的UILabel
- (void)setUpRefresh
{
    //上拉刷新控件
    //创建Label
    UILabel *refreshLabel = [[UILabel alloc] init];
    //设置label文字
    refreshLabel.text = @"上拉加载更多数据";
    //设置颜色
    refreshLabel.backgroundColor = [UIColor redColor];
    //设置文字的位置
    refreshLabel.textAlignment = NSTextAlignmentCenter;
    //设置文字颜色
    refreshLabel.textColor = [UIColor whiteColor];
    //设置高度
    refreshLabel.XFJ_Height = 35;
    //添加到footerView
    self.tableView.tableFooterView = refreshLabel;
    //赋值
    self.refreshLabel = refreshLabel;

    //下拉刷新控件
    [self setTitleRefresh];
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

七 底部刷新控件的业务逻辑

1 由于我们需要时刻的监听用户拖拽tableView的时候,来显示刷新控件的显示状态.因为UITableView是继承UIScrollView的,所以也同时拥有了UIScrollView中的方法.
2 监听用户拖动的时候调用
#pragma mark - 代理方法(拖动的时候调用)
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    //调用尾部方法
    [self dealFooter];
    //调用头部方法
    [self dealHeader];
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
3 处理用户往上拖拽的时候刷新条的业务逻辑
#pragma mark - footer处理尾部刷新拖动的时候逻辑
- (void)dealFooter
{
    if (self.item.count == 0) return;
    if (self.isFooterRefresh) return;
    //计算偏移量
    CGFloat offset = self.tableView.contentSize.height + self.tableView.contentInset.bottom - self.tableView.XFJ_Height;
    //判断
    if (self.tableView.contentOffset.y >= offset) {

        //开始刷新尾部数据
        [self footerBeginRefresh];
    }
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
4 tableView开始刷新部分
#pragma mark - footer开始刷新
- (void)footerBeginRefresh
{
    //如果尾部正在刷新就直接返回
    if (self.isFooterRefresh) return;
    //是否刷新数据
    self.footerRefresh = YES;
    //修改label文字
    self.refreshLabel.text = @"正在加载更多数据...";
    //修改label背景颜色
    self.refreshLabel.backgroundColor = [UIColor blueColor];
    //上拉刷新加载更多帖子
    [self setUpMoreTopics];
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
5 tableView结束刷新部分
#pragma mark - footer结束刷新
- (void)footerEndRefresh
{
    //结束刷新
    self.footerRefresh = NO;
    //恢复背景颜色
    self.refreshLabel.backgroundColor = [UIColor redColor];
    //恢复文字
    self.refreshLabel.text = @"上拉加载更多数据";
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

八 顶部刷新控件的业务逻辑

1 创建顶部刷新条
2 注意添加的位置
3 代码部分:
#pragma mark - 创建下拉刷新控件
- (void)setTitleRefresh
{
    //创建label
    UILabel *header = [[UILabel alloc] init];
    //设置背景颜色
    header.backgroundColor = [UIColor redColor];
    //设置文字颜色
    header.textColor = [UIColor whiteColor];
    //设置文字
    header.text = @"下拉加载跟多数据";
    //设置尺寸
    header.XFJ_Height =  50;
    //位置
    header.XFJ_Y = - header.XFJ_Height;
    //宽度
    header.XFJ_Width = self.tableView.XFJ_Width;
    //添加
    [self.tableView addSubview:header];
    //设置文字居中
    header.textAlignment = NSTextAlignmentCenter;
    //赋值
    self.header = header;
    //启动程序需要刷新
    [self headerBeginRefresh];
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
4 监听用户往下拖动tableView,刷新内容的监听(使用代理方法)
—-> 4.1 用户停止拖动的时候调用
#pragma mark - 拖动停止的时候调用
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
    //如果头部正在刷新就不要刷新了
    if (self.isHeaderRefresh) return;
    //计算偏移量
    CGFloat offset = - (self.tableView.contentInset.top + self.header.XFJ_Height);
    //判断(通过判断偏移量来改变刷新控件上的文字的显示)
    if (self.tableView.contentOffset.y <= offset) {
        //开始刷新
        [self headerBeginRefresh];
    }
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
—-> 4.2 用户拖动的时候调用处理业务逻辑
#pragma mark - header处理头部逻辑
- (void)dealHeader
{
    //如果header还没有被创建的话就直接返回
    if (self.header == nil) return;
    //如果头部控件正在刷新
    if (self.isHeaderRefresh) return;
    //计算偏移量
    CGFloat offsetInset = - (self.tableView.contentInset.top + self.header.XFJ_Height);
    //判断
    if (self.tableView.contentOffset.y <= offsetInset) {
        //改变文字
        self.header.text = @"松开立即刷新";
        self.header.backgroundColor = [UIColor blueColor];
    }else {
        self.header.text = @"下拉可以刷新";
        self.header.backgroundColor = [UIColor orangeColor];
    }
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
4.3 顶部刷新条开始刷新
#pragma mark - header开始刷新
- (void)headerBeginRefresh
{
    //判断如果正在刷新就直接返回
    if (self.isHeaderRefresh) return;
    //允许刷新
    self.headerRefresh = YES;
    //允许刷新的文字
    self.header.text = @"正在刷新数据...";
    //改变背景颜色
    self.header.backgroundColor = [UIColor brownColor];
    //增大内边距
    [UIView animateWithDuration:0.25 animations:^{
        UIEdgeInsets offsetIns = self.tableView.contentInset;
        offsetIns.top += self.header.XFJ_Height;
        self.tableView.contentInset = offsetIns;

        CGPoint offset = self.tableView.contentOffset;
        offset.y = - offsetIns.top;
        self.tableView.contentOffset = offset;
    }];
    //调用刷新方法
    [self setLoadNews];
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
4.4 顶部刷新条结束刷新
#pragma mark - header结束刷新
- (void)headerEndRefresh
{
    //刷新完毕后结束刷新
    self.headerRefresh = NO;
    //减小内边距
    [UIView animateWithDuration:0.25 animations:^{
        UIEdgeInsets offsetIns = self.tableView.contentInset;
        offsetIns.top -= self.header.XFJ_Height;
        self.tableView.contentInset = offsetIns;
    }];
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

九 处理细节

1 程序一启动底部的刷新条会短暂的出现在顶部位置.
—-> 解决方案: 在tableView一刷新就会调用的方法中控制.(通过模型的数量老控制)
#pragma mark - 行数
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    //隐藏开始启动程序的label的片刻出现
    self.refreshLabel.hidden = (self.item.count == 0);
    return self.item.count;
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
2 程序开始启动的时候,自动刷新正常,但是当手动拖拽tableView进行刷新的时候,刷新的数量并不能控制,这是不合理的.(请求数据的时候控制了服务器返回的数据量)
—-> 解决方案: 通过定义一个第三方属性来记录状态,是否停止刷新和是否开始刷新.用if来做出判断.

十 刷新功能的追加模式(查看是否有数据重复)

1 通过查看写入的plist文件,查看到在maxtime中记录了每一次返回给客户端其参数的最后一个数字.比如:刷新的时候,接收到服务器的数据是50;49;48;47的时候,客户端在刷新完后,将47返回给服务器,然后服务器会根据接收到的请求参数,将位于47后面的信息返回给客户端,这样就达到了刷新的目的同时不会重复
2 有些公司是通过page来发送,来判断返回的数据是否重叠(不推荐使用,因为会照成错漏).

十一 知识点补充

1 我们是通过插入label的方式来实现刷新的目的,同理在很多app中会出现中间某些部位有广告弹出来,我们也可以往里面插入广告.
2 补充一些有关于宏的知识:
—-> 2.1 在宏里面,两个”##”的作用:链接两个标识符
#define method(name) - (void)load##name {}
method(abc)  //- (void)loadabc {}
method(ddd)  //- (void)loadddd {}
method(ttt)  //- (void)loadttt {}
 
 
  • 1
  • 2
  • 3
  • 4
—-> 2.2 在宏里面,一个”#”的作用:给右边的标识符加上双引号.
#define test(name) @#name
test(abc) // @"abc"
 
 
  • 1
  • 2

十二 总结

1 该部分只是简单的tableView刷新部分,里面还有很多的不足,需要修改.作者里面表达的逻辑还是很容易明白的,只是我希望看过我这篇博客的人很有所收获,特别是要明白原理图.里面牵扯到了一些计算,不懂是没法做的.
2 最后,明天我将为大家继续完善百思不得姐app.如果大家觉得我写的博客还满意的话,麻烦大家关注我的官方博客,有什么问题,大家可以给我留言,我将一 一为大家解决,谢谢!!!!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值