03-项目中的数据刷新

  • 项目中经常会用到上拉下拉刷新,通常使用框架
  • 一般公司都会对自己app的上拉下拉刷新作特性化定制,而且全局多处用到.所以需要对自定义的上拉下拉刷新进行封装

代码如下(文字效果)

下拉刷新封装 (继承MJRefreshNormalHeader)

.h文件

#import 

@interface XMGRefreshHeader : MJRefreshNormalHeader

@end

.m文件

#import "XMGRefreshHeader.h"

@interface XMGRefreshHeader()
/** logo */
@property (nonatomic, weak) UIImageView *logo;
@end

@implementation XMGRefreshHeader

/**
 *  初始化
 */
- (void)prepare
{
    [super prepare];
    
    self.automaticallyChangeAlpha = YES;
// 修改时间文字的颜色
    self.lastUpdatedTimeLabel.textColor = [UIColor orangeColor];
// 修改刷新状态的颜色
    self.stateLabel.textColor = [UIColor orangeColor];
// 设置state状态下的文字 
    [self setTitle:@"赶紧下拉吧" forState:MJRefreshStateIdle];
    [self setTitle:@"赶紧松开吧" forState:MJRefreshStatePulling];
    [self setTitle:@"正在加载数据..." forState:MJRefreshStateRefreshing];
// 隐藏时间
    //    self.lastUpdatedTimeLabel.hidden = YES;
// 隐藏刷新状态
    //    self.stateLabel.hidden = YES;
// 添加控件
     [self addSubview:[[UISwitch alloc] init]];
   
// 添加logo 
    UIImageView *logo = [[UIImageView alloc] init];
    logo.image = [UIImage imageNamed:@"bd_logo1"];
    [self addSubview:logo];
    self.logo = logo;
}

/**
 *  摆放子控件
 */
- (void)placeSubviews
{
    [super placeSubviews];
    
    self.logo.xmg_width = self.xmg_width;
    self.logo.xmg_height = 50;
    self.logo.xmg_x = 0;
    self.logo.xmg_y = - 50; // 自己控制
}

上拉刷新封装(继承MJRefreshAutoNormalFooter)

.h文件

#import 

@interface XMGRefreshFooter : MJRefreshAutoNormalFooter

@end

.m文件

#import "XMGRefreshFooter.h"

@implementation XMGRefreshFooter

- (void)prepare
{
    [super prepare];
    
    self.stateLabel.textColor = [UIColor redColor];
    
    [self addSubview:[UIButton buttonWithType:UIButtonTypeContactAdd]];
    
    // 刷新控件出现一半就会进入刷新状态
//    self.triggerAutomaticallyRefreshPercent = 0.5;
    
    // 不要自动刷新
//    self.automaticallyRefresh = NO;
}

@end

项目中使用

@interface XMGAllViewController ()
/** 所有的帖子数据 */
@property (nonatomic, strong) NSMutableArray *topics;
/** 下拉刷新的提示文字 */
@property (nonatomic, weak) UILabel *label;
/** maxtime : 用来加载下一页数据 */
@property (nonatomic, copy) NSString *maxtime;
/** 任务管理者 */
@property (nonatomic, strong) AFHTTPSessionManager *manager;
@end
- (AFHTTPSessionManager *)manager
{
    if (!_manager) {
        _manager = [AFHTTPSessionManager manager];
    }
    return _manager;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    [self setupRefresh];
}

// 刷新
- (void)setupRefresh
{
    self.tableView.mj_header = [XMGRefreshHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewTopics)];
    // 希望一进来就刷新
    [self.tableView.mj_header beginRefreshing];

    self.tableView.mj_footer = [XMGRefreshFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreTopics)];
}

#pragma mark - 数据加载
- (void)loadNewTopics
{
    // 取消所有请求
   [self.manager.tasks makeObjectsPerformSelector:@selector(cancel)];
    // 参数
    NSMutableDictionary *params = [NSMutableDictionary dictionary];
    params[@"a"] = @"list";
    params[@"c"] = @"data";
    
    // 发送请求
    [[AFHTTPSessionManager manager] GET:@"http://api.budejie.com/api/api_open.php" parameters:params success:^(NSURLSessionDataTask * _Nonnull task, id  _Nonnull responseObject) {
        // 存储maxtime(方便用来加载下一页数据)
        self.maxtime = responseObject[@"info"][@"maxtime"];
        
        // 字典数组 -> 模型数组
        self.topics = [XMGTopic mj_objectArrayWithKeyValuesArray:responseObject[@"list"]];
        
        // 刷新表格
        [self.tableView reloadData];        
        // 让[刷新控件]结束刷新
        [self.tableView.mj_header endRefreshing];
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        XMGLog(@"请求失败 - %@", error);
        
        // 让[刷新控件]结束刷新
        [self.tableView.mj_header endRefreshing];
    }];
}

- (void)loadMoreTopics
{
    // 取消所有的请求
   [self.manager.tasks makeObjectsPerformSelector:@selector(cancel)];
    // 参数
    NSMutableDictionary *params = [NSMutableDictionary dictionary];
    params[@"a"] = @"list";
    params[@"c"] = @"data";
    params[@"maxtime"] = self.maxtime;
    
    // 发送请求
    [[AFHTTPSessionManager manager] GET:@"http://api.budejie.com/api/api_open.php" parameters:params success:^(NSURLSessionDataTask * _Nonnull task, id  _Nonnull responseObject) {
        // 存储这页对应的maxtime
        self.maxtime = responseObject[@"info"][@"maxtime"];
        
        // 字典数组 -> 模型数组
        NSArray *moreTopics = [XMGTopic mj_objectArrayWithKeyValuesArray:responseObject[@"list"]];
        [self.topics addObjectsFromArray:moreTopics];
        
        // 刷新表格
        [self.tableView reloadData];
        
        // 让[刷新控件]结束刷新
        [self.tableView.mj_footer endRefreshing];
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        XMGLog(@"请求失败 - %@", error);
        
        // 让[刷新控件]结束刷新
        [self.tableView.mj_footer endRefreshing];
    }];
}

拓展分析

1. addObject:和addObjectsFromArray:的区别

self.topics = @[20, 19, 18]
moreTopics = @[17, 16, 15]

self.topics = @[20, 19, 18, @[17, 16, 15]]
[self.topics addObject:moreTopics];

self.topics = @[20, 19, 18, 17, 16, 15]
[self.topics addObjectsFromArray:moreTopics];

2. 常见分页方法

F1799B71-E97E-4337-8D9E-B18CCDEA4C5A.png

方法一:
缺点:可能加载重数据

方法二:
大多数公司采用的方法
原理:明确的告诉服务器我数据加载到哪

分页在项目示例中的解析

在下拉的 - (void)loadNewTopics 方法中 ,存储一下它的maxtime

// 存储maxtime(方便用来加载下一页数据)
self.maxtime = responseObject[@"info"][@"maxtime"];

在上拉 - (void)loadMoreTopics 中要传maxtime给后台,同时maxtime的值根据不断地恶上拉要不断更新,所以在上拉后,将后台返回的maxtime不断存储下来

// 存储这页对应的maxtime
self.maxtime = responseObject[@"info"][@"maxtime"];

3. 上拉下拉刷新出现的一些问题

  • 当上拉下拉同时出现时,会出现数据漏掉问题
29891B6C-6FD6-4095-9404-68F4574C37B4.png

解决:
上拉时,取消其它的所有请求 ,同时取消刷新控件
下拉时,取消其它的所有请求 ,同时取消刷新控件

// 所有的任务被任务管理者统一管理
// 此句代码的意思就是取消其它所有的请求
//  一个请求任务被取消了(cancel), 会自动调用AFN请求的failure这个block
// 所以不需要再单独去写取消刷新控件
 [self.manager.tasks makeObjectsPerformSelector:@selector(cancel)];

4. 子类化AFHTTPSessionManager

需求:因为有可能项目中多地方使用,并且会做一些统一化设置,所以将其抽出一个子类,方便项目中使用(官方建议如此使用)

代码如下:

#import 

@interface XMGHTTPSessionManager : AFHTTPSessionManager

@end
#import "XMGHTTPSessionManager.h"

@implementation XMGHTTPSessionManager

- (instancetype)initWithBaseURL:(NSURL *)url
{
    if (self = [super initWithBaseURL:url]) {
//        self.securityPolicy.validatesDomainName = NO;
//        self.responseSerializer = nil;
//        self.requestSerializer = nil;
    }
    return self;
}

@end

你可能感兴趣的:(03-项目中的数据刷新)