// // MJTableViewController.m // BaseProject // // Created by WindShan on 2016/12/7. // Copyright © 2016年 WindShan. All rights reserved. // #import "MJTableViewController.h" #import "MJChiBaoZiHeader.h" #import "MJChiBaoZiFooter.h" #define MJPerformSelectorLeakWarning(Stuff) \ do { \ _Pragma("clang diagnostic push") \ _Pragma("clang diagnostic ignored \"-Warc-performSelector-leaks\"") \ Stuff; \ _Pragma("clang diagnostic pop") \ } while (0) static const CGFloat MJDuration = 2.0; /** * 随机数据 */ #define MJRandomData [NSString stringWithFormat:@"随机数据---%d", arc4random_uniform(1000000)] @interface MJTableViewController () /** 用来显示的假数据 */ @property (strong, nonatomic) NSMutableArray *data; @end @implementation MJTableViewController - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.data.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *ID = @"cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID]; } cell.textLabel.text = [NSString stringWithFormat:@"%@ - %@", indexPath.row % 2?@"push":@"modal", self.data[indexPath.row]]; return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { // MJTestViewController *test = [[MJTestViewController alloc] init]; // if (indexPath.row % 2) { // [self.navigationController pushViewController:test animated:YES]; // } else { // UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:test]; // [self presentViewController:nav animated:YES completion:nil]; // } } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. //tableview self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT-64) style:UITableViewStylePlain]; self.tableView.delegate = self; self.tableView.dataSource = self; self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; [self.view addSubview:self.tableView]; self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"]; [self setMethod:self.title]; // 根据方法名字调用该方法 MJPerformSelectorLeakWarning( [self performSelector:NSSelectorFromString(self.method) withObject:nil]; ); } static char MethodKey; - (void)setMethod:(NSString *)method { objc_setAssociatedObject(self, &MethodKey, method, OBJC_ASSOCIATION_COPY_NONATOMIC); } - (NSString *)method { return objc_getAssociatedObject(self, &MethodKey); } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } #pragma mark - 示例代码 #pragma mark UITableView + 下拉刷新 默认 - (void)example01 { __weak __typeof(self) weakSelf = self; // 设置回调(一旦进入刷新状态就会调用这个refreshingBlock) self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{ [weakSelf loadNewData]; }]; // 马上进入刷新状态 [self.tableView.mj_header beginRefreshing]; } #pragma mark UITableView + 下拉刷新 动画图片 - (void)example02 { // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadNewData方法) self.tableView.mj_header = [MJChiBaoZiHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewData)]; // 马上进入刷新状态 [self.tableView.mj_header beginRefreshing]; } #pragma mark UITableView + 下拉刷新 隐藏时间 - (void)example03 { // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadNewData方法) MJRefreshNormalHeader *header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewData)]; // 设置自动切换透明度(在导航栏下面自动隐藏) header.automaticallyChangeAlpha = YES; // 隐藏时间 header.lastUpdatedTimeLabel.hidden = YES; // 马上进入刷新状态 [header beginRefreshing]; // 设置header self.tableView.mj_header = header; } #pragma mark UITableView + 下拉刷新 隐藏状态和时间 - (void)example04 { // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadNewData方法) MJChiBaoZiHeader *header = [MJChiBaoZiHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewData)]; // 隐藏时间 header.lastUpdatedTimeLabel.hidden = YES; // 隐藏状态 header.stateLabel.hidden = YES; // 马上进入刷新状态 [header beginRefreshing]; // 设置header self.tableView.mj_header = header; } #pragma mark UITableView + 下拉刷新 自定义文字 - (void)example05 { // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadNewData方法) MJRefreshNormalHeader *header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewData)]; // 设置文字 [header setTitle:@"Pull down to refresh" forState:MJRefreshStateIdle]; [header setTitle:@"Release to refresh" forState:MJRefreshStatePulling]; [header setTitle:@"Loading ..." forState:MJRefreshStateRefreshing]; // 设置字体 header.stateLabel.font = [UIFont systemFontOfSize:15]; header.lastUpdatedTimeLabel.font = [UIFont systemFontOfSize:14]; // 设置颜色 header.stateLabel.textColor = [UIColor redColor]; header.lastUpdatedTimeLabel.textColor = [UIColor blueColor]; // 马上进入刷新状态 [header beginRefreshing]; // 设置刷新控件 self.tableView.mj_header = header; } #pragma mark UITableView + 下拉刷新 自定义刷新控件 - (void)example06 { // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadNewData方法) // self.tableView.mj_header = [MJDIYHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewData)]; // [self.tableView.mj_header beginRefreshing]; } #pragma mark UITableView + 上拉刷新 默认 - (void)example11 { [self example01]; __weak __typeof(self) weakSelf = self; // 设置回调(一旦进入刷新状态就会调用这个refreshingBlock) self.tableView.mj_footer = [MJRefreshAutoNormalFooter footerWithRefreshingBlock:^{ [weakSelf loadMoreData]; }]; } #pragma mark UITableView + 上拉刷新 动画图片 - (void)example12 { [self example01]; // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadMoreData方法) self.tableView.mj_footer = [MJChiBaoZiFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreData)]; } #pragma mark UITableView + 上拉刷新 隐藏刷新状态的文字 - (void)example13 { [self example01]; // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadMoreData方法) MJChiBaoZiFooter *footer = [MJChiBaoZiFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreData)]; // 当上拉刷新控件出现50%时(出现一半),就会自动刷新。这个值默认是1.0(也就是上拉刷新100%出现时,才会自动刷新) // footer.triggerAutomaticallyRefreshPercent = 0.5; // 隐藏刷新状态的文字 footer.refreshingTitleHidden = YES; // 设置footer self.tableView.mj_footer = footer; } #pragma mark UITableView + 上拉刷新 全部加载完毕 - (void)example14 { [self example01]; // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadLastData方法) self.tableView.mj_footer = [MJRefreshAutoNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadLastData)]; // 其他 self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"恢复数据加载" style:UIBarButtonItemStyleDone target:self action:@selector(reset)]; } - (void)reset { [self.tableView.mj_footer setRefreshingTarget:self refreshingAction:@selector(loadMoreData)]; // [self.tableView.mj_footer beginRefreshing]; [self.tableView.mj_footer resetNoMoreData]; } #pragma mark UITableView + 上拉刷新 禁止自动加载 - (void)example15 { [self example01]; // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadMoreData方法) MJRefreshAutoNormalFooter *footer = [MJRefreshAutoNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreData)]; // 禁止自动加载 footer.automaticallyRefresh = NO; // 设置footer self.tableView.mj_footer = footer; } #pragma mark UITableView + 上拉刷新 自定义文字 - (void)example16 { [self example01]; // 添加默认的上拉刷新 // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadMoreData方法) MJRefreshAutoNormalFooter *footer = [MJRefreshAutoNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreData)]; // 设置文字 [footer setTitle:@"Click or drag up to refresh" forState:MJRefreshStateIdle]; [footer setTitle:@"Loading more ..." forState:MJRefreshStateRefreshing]; [footer setTitle:@"No more data" forState:MJRefreshStateNoMoreData]; // 设置字体 footer.stateLabel.font = [UIFont systemFontOfSize:17]; // 设置颜色 footer.stateLabel.textColor = [UIColor blueColor]; // 设置footer self.tableView.mj_footer = footer; } #pragma mark UITableView + 上拉刷新 加载后隐藏 - (void)example17 { [self example01]; // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadOnceData方法) self.tableView.mj_footer = [MJRefreshAutoNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadOnceData)]; } #pragma mark UITableView + 上拉刷新 自动回弹的上拉01 - (void)example18 { [self example01]; // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadMoreData方法) self.tableView.mj_footer = [MJRefreshBackNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreData)]; // 设置了底部inset self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 30, 0); // 忽略掉底部inset self.tableView.mj_footer.ignoredScrollViewContentInsetBottom = 30; } #pragma mark UITableView + 上拉刷新 自动回弹的上拉02 - (void)example19 { [self example01]; // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadLastData方法) // self.tableView.mj_footer = [MJChiBaoZiFooter2 footerWithRefreshingTarget:self refreshingAction:@selector(loadLastData)]; // self.tableView.mj_footer.automaticallyChangeAlpha = YES; } #pragma mark UITableView + 上拉刷新 自定义刷新控件(自动刷新) - (void)example20 { [self example01]; // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadMoreData方法) //self.tableView.mj_footer = [MJDIYAutoFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreData)]; } #pragma mark UITableView + 上拉刷新 自定义刷新控件(自动回弹) - (void)example21 { [self example01]; // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadMoreData方法) // self.tableView.mj_footer = [MJDIYBackFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreData)]; } #pragma mark - 数据处理相关 #pragma mark 下拉刷新数据 - (void)loadNewData { // 1.添加假数据 for (int i = 0; i<5; i++) { [self.data insertObject:MJRandomData atIndex:0]; } // 2.模拟2秒后刷新表格UI(真实开发中,可以移除这段gcd代码) __weak UITableView *tableView = self.tableView; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(MJDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // 刷新表格 [tableView reloadData]; // 拿到当前的下拉刷新控件,结束刷新状态 [tableView.mj_header endRefreshing]; }); } #pragma mark 上拉加载更多数据 - (void)loadMoreData { // 1.添加假数据 for (int i = 0; i<5; i++) { [self.data addObject:MJRandomData]; } // 2.模拟2秒后刷新表格UI(真实开发中,可以移除这段gcd代码) __weak UITableView *tableView = self.tableView; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(MJDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // 刷新表格 [tableView reloadData]; // 拿到当前的上拉刷新控件,结束刷新状态 [tableView.mj_footer endRefreshing]; }); } #pragma mark 加载最后一份数据 - (void)loadLastData { // 1.添加假数据 for (int i = 0; i<5; i++) { [self.data addObject:MJRandomData]; } // 2.模拟2秒后刷新表格UI(真实开发中,可以移除这段gcd代码) __weak UITableView *tableView = self.tableView; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(MJDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // 刷新表格 [tableView reloadData]; // 拿到当前的上拉刷新控件,变为没有更多数据的状态 [tableView.mj_footer endRefreshingWithNoMoreData]; }); } #pragma mark 只加载一次数据 - (void)loadOnceData { // 1.添加假数据 for (int i = 0; i<5; i++) { [self.data addObject:MJRandomData]; } // 2.模拟2秒后刷新表格UI(真实开发中,可以移除这段gcd代码) __weak UITableView *tableView = self.tableView; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(MJDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // 刷新表格 [tableView reloadData]; // 隐藏当前的上拉刷新控件 tableView.mj_footer.hidden = YES; }); } - (NSMutableArray *)data { if (!_data) { self.data = [NSMutableArray array]; for (int i = 0; i<5; i++) { [self.data addObject:MJRandomData]; } } return _data; } /* #pragma mark - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // Get the new view controller using [segue destinationViewController]. // Pass the selected object to the new view controller. } */ @end