热更新demo

TPTableViewController.m 19KB

    // // TPTableViewController.m // ThePaperDemo // // Created by scar1900 on 14/10/21. // Copyright (c) 2014年 scar1900. All rights reserved. // #import "TPTableViewController.h" @implementation loadFootView @synthesize state = _state; @synthesize isMall; @synthesize delegate; - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.backgroundColor = [UIColor clearColor]; [self addSubview:self.gifView]; [self addSubview:self.textLabel]; self.state = RefreshStateNormal; isMall = NO; } return self; } - (SCGIFImageView*)gifView { if (!_gifView) { NSString *filePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingFormat:@"/%@", Bundle(@"frontPage/loading.gif")]; NSData* imageData = [NSData dataWithContentsOfFile:filePath]; _gifView = [[SCGIFImageView alloc]initWithFrame:CGRectMake(CGRectGetWidth(self.bounds)/2-25/2, 10, 25, 25)]; [_gifView setData:imageData]; _gifView.animating = NO; } return _gifView; } - (UILabel*)textLabel { if (!_textLabel) { _textLabel = [[UILabel alloc]initWithFrame:CGRectMake(0,CGRectGetMaxY(self.gifView.frame)+5 , CGRectGetWidth(self.bounds), 20)]; _textLabel.textAlignment = NSTextAlignmentCenter; _textLabel.textColor = [UIColor colorWithHexString:TextGray]; } _textLabel.font = appFont(11, NO); return _textLabel; } - (void)setState:(RefreshState )sta { if (_state == sta) return; _state = sta; if (sta == RefreshStateNormal) { self.gifView.hidden = YES; self.textLabel.hidden = NO; if (isMall) self.textLabel.frame = CGRectMake(0, 20, CGRectGetWidth(self.bounds), 20); else self.textLabel.frame = self.bounds; self.textLabel.text = @"上拉加载数据"; self.gifView.animating = NO; }else if (sta == RefreshStateRefreshing) { self.textLabel.hidden = NO; self.gifView.hidden = NO; self.gifView.animating = YES; self.textLabel.frame = CGRectMake(0,CGRectGetMaxY(self.gifView.frame)+5 , CGRectGetWidth(self.bounds), 20); self.textLabel.text = @"正在加载"; if ([delegate conformsToProtocol:@protocol(LoadFootDelegate)] && [delegate respondsToSelector:@selector(startLoad)]) { [delegate startLoad]; } }else if (sta == RefreshStateCancel) { self.state = RefreshStateNormal; }else if (sta == RefreshStateSucess) { self.state = RefreshStateNormal; }else if (sta == RefreshStateFailed) { // ShowTextMessage(@"加载失败"); self.state = RefreshStateNormal; }else if (sta == RefreshStateNoMore) { self.gifView.hidden = YES; self.textLabel.hidden = NO; if (isMall) self.textLabel.frame = CGRectMake(0, 20, CGRectGetWidth(self.bounds), 20); else self.textLabel.frame = self.bounds; self.textLabel.text = @"没有更多数据"; self.gifView.animating = NO; }else if (sta == RefreshStatePulling) { self.gifView.hidden = YES; self.textLabel.hidden = NO; if (isMall) self.textLabel.frame = CGRectMake(0, 20, CGRectGetWidth(self.bounds), 20); else self.textLabel.frame = self.bounds; self.textLabel.text = @"释放加载数据"; self.gifView.animating = NO; } } - (void)layoutSubviews { [super layoutSubviews]; } @end @implementation refreshHeadView @synthesize state = _state; @synthesize contentOffset = _contentOffset; @synthesize lastUpdateDate = _lastUpdateDate; @synthesize delegate; - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.backgroundColor = [UIColor clearColor]; [self addSubview:self.gifView]; [self addSubview:self.timeLabel]; self.timeLabel.text = @""; self.state = RefreshStateNormal; } return self; } - (SCGIFImageView*)gifView { if (!_gifView) { NSString *filePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingFormat:@"/%@", Bundle(@"frontPage/loading.gif")]; NSData* imageData = [NSData dataWithContentsOfFile:filePath]; _gifView = [[SCGIFImageView alloc]initWithFrame:CGRectMake(CGRectGetWidth(self.bounds)/2-25/2, 10, 25, 25)]; [_gifView setData:imageData]; _gifView.animating = NO; } return _gifView; } - (UILabel*)timeLabel { if (!_timeLabel) { _timeLabel = [[UILabel alloc]initWithFrame:CGRectMake(0,CGRectGetMaxY(self.gifView.frame)+5 , CGRectGetWidth(self.bounds), 20)]; _timeLabel.backgroundColor = [UIColor clearColor]; _timeLabel.textAlignment = NSTextAlignmentCenter; } _timeLabel.font = appFont(11, NO); _timeLabel.textColor = [UIColor colorWithHexString:TextBlack]; /** * bug:5339(首页:夜间模式下刷新,“刚刚““正在刷新”没反色) */ return _timeLabel; } - (void)setState:(RefreshState )sta { if (_state == sta) return; _state = sta; if (sta == RefreshStateNormal) { self.gifView.animating = NO; }else if (sta == RefreshStateIsPulling) { self.gifView.animating = NO; [self setLastUpdateTimeLabel:self.lastUpdateDate]; self.state = RefreshStateNormal; }else if (sta == RefreshStateRefreshing) { self.gifView.animating = YES; self.timeLabel.text = @"正在刷新"; //设置0.5s延迟 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ if ([delegate conformsToProtocol:@protocol(refreshHeadDelegate)] && [delegate respondsToSelector:@selector(startRefresh)]) { [delegate startRefresh]; } }); }else if (sta == RefreshStateCancel) { self.state = RefreshStateNormal; }else if (sta == RefreshStateSucess) { self.lastUpdateDate = [NSDate date]; self.state = RefreshStateNormal; } } - (void)setContentOffset:(CGPoint)Offset { _contentOffset = Offset; } - (void)setLastUpdateDate:(NSDate *)date { _lastUpdateDate = date; } - (void)setLastUpdateTimeLabel:(NSDate*)lastDate{ self.timeLabel.text = getUpdateStringFromDate(lastDate); } - (void)layoutSubviews { [super layoutSubviews]; } @end @interface TPTableViewController ()<UITableViewDataSource,UITableViewDelegate,refreshHeadDelegate,LoadFootDelegate> { BOOL isCanRefresh; BOOL isCanLoad; // BOOL isPull; } @property(nonatomic, assign)BOOL isFirstRefresh; @end @implementation TPTableViewController @synthesize tableView; @synthesize nextUrl = _nextUrl; @synthesize isFirstRefresh; @synthesize contentInsetTop = _contentInsetTop; - (id)init { if (self = [super init]) { CGFloat width = [UIScreen mainScreen].applicationFrame.size.width; CGFloat height = [UIScreen mainScreen].applicationFrame.size.height; self.tableView = [[HeaderInsetTableView alloc] initWithFrame:CGRectMake(0, 0, width, height) style:UITableViewStylePlain]; self.tableView.delegate = self; self.tableView.dataSource = self; self.tableView.autoresizingMask = AutoresizingFull; self.tableView.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0); self.tableView.backgroundColor = [UIColor clearColor]; self.isFirstRefresh = YES; self.tableView.delaysContentTouches = NO; isCanLoad = NO; isCanRefresh = NO; } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.view.backgroundColor = [UIColor colorWithHexString:@"0xe6e9e7"]; // isPull = NO; self.tableView.frame = self.view.bounds; self.tableView.clipsToBounds = NO; self.contentInsetTop = 0; [self.view addSubview:self.tableView]; } - (void)setContentInsetTop:(CGFloat)top { _contentInsetTop = top; self.tableView.contentInset = UIEdgeInsetsMake(top, 0, 0, 0); } - (void)configCanRefresh:(BOOL)canRefresh canLoad:(BOOL)canLoad { if (canRefresh || canLoad) { if (canRefresh) { isCanRefresh = YES; [self.tableView addSubview:self.refreshHeader]; }else { isCanRefresh = NO; [self.refreshHeader removeFromSuperview]; } if (canLoad) { isCanLoad = YES; self.tableView.tableFooterView = self.loadFooter; }else { isCanLoad = NO; self.tableView.tableFooterView = nil; } [self addObserver:self forKeyPath:@"self.tableView.contentOffset" options:NSKeyValueObservingOptionNew context:nil]; } } - (void) viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; self.tableView.editing = NO; } - (refreshHeadView*)refreshHeader { if (!_refreshHeader) { _refreshHeader = [[refreshHeadView alloc]initWithFrame:CGRectMake(0,-60 ,CGRectGetWidth(self.view.bounds) , 0)]; _refreshHeader.delegate = self; } return _refreshHeader; } - (loadFootView*)loadFooter { if (!_loadFooter) { _loadFooter = [[loadFootView alloc]initWithFrame:CGRectMake(0, CGRectGetHeight(self.tableView.bounds) ,CGRectGetWidth(self.view.bounds) , 60)]; _loadFooter.hidden = YES; _loadFooter.delegate = self; } return _loadFooter; } - (void)setNextUrl:(NSString *)url { _nextUrl = url; // isPull = NO; if (isBlankString(url)) { [self noMoreLoad]; }else { self.loadFooter.state = RefreshStateNormal; } } #pragma mark UITableViewDelegate and UITableViewDataSource - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 20; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return 44.0; } - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { return 0; } - (UITableViewCell *)tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString* httpTableViewCellIdentefier = @"TPHttpTableViewController cell"; UITableViewCell* cell = [table dequeueReusableCellWithIdentifier:httpTableViewCellIdentefier]; if (nil == cell) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:httpTableViewCellIdentefier]; cell.backgroundColor = [UIColor whiteColor]; } cell.textLabel.text = [NSString stringWithFormat:@"section:%ld,row=%ld",(long)indexPath.row, (long)indexPath.row]; return cell; } //- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { // // This will create a "invisible" footer // return 0.01f; //} // //- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section { // // To "clear" the footer view // return [UIView new]; //} #pragma mark - refresh and load method - (void)manualRefresh { self.loadFooter.state = RefreshStateNormal; [UIView animateWithDuration:0.2 animations:^{ self.tableView.contentInset = UIEdgeInsetsMake(self.contentInsetTop+60.f, 0, 0, 0); self.tableView.contentOffset = CGPointMake(0, 0-self.contentInsetTop-60.f); }]; self.refreshHeader.state = RefreshStateRefreshing; isFirstRefresh = NO; } - (void)startRefresh { [self pullRefreshHandler]; // isPull = YES; self.loadFooter.state = RefreshStateNormal; } - (void)startLoad { // if (isPull) { // return; // } if (isBlankString(self.nextUrl)) { self.nextUrl = @""; return; } [self pullLoadMoreHander]; } - (void)pullRefreshHandler{ } - (void)pullLoadMoreHander { } - (void)firstAutoRefreshHandler { if (self.loadFooter.state == RefreshStateNoMore) { //bug5443: 问吧分类页:快速滑动后,上拉加载,加载到底部会显示“上拉加载数据” return; } self.loadFooter.state = RefreshStateNormal; if (isFirstRefresh) { [UIView animateWithDuration:0.2 animations:^{ self.tableView.contentInset = UIEdgeInsetsMake(self.contentInsetTop+60, 0, 0, 0); self.tableView.contentOffset = CGPointMake(0, 0-self.contentInsetTop-60.f); }]; self.refreshHeader.state = RefreshStateRefreshing; } self.isFirstRefresh = NO; } - (void)needNoFirstAutoRefresh { self.isFirstRefresh = NO; } - (void)endRefresh { [UIView animateWithDuration:0.2 animations:^{ self.refreshHeader.state = RefreshStateSucess; self.tableView.contentInset = UIEdgeInsetsMake(self.contentInsetTop, 0, 0, 0); }]; } - (void)cancelRefresh { [UIView animateWithDuration:0.2 animations:^{ self.refreshHeader.state = RefreshStateCancel; self.tableView.contentInset = UIEdgeInsetsMake(self.contentInsetTop, 0, 0, 0); }]; } - (void)noMoreLoad { self.loadFooter.state = RefreshStateNoMore; } - (void)loadSuccess { self.loadFooter.state = RefreshStateSucess; } - (void)loadFailed { self.loadFooter.state = RefreshStateFailed; } - (void)cancelLoadMore { self.loadFooter.state = RefreshStateNormal; } #pragma mark - remote method - (void)startWaitCursor:(int)actionTag { } - (void)stopWaitCursor:(int)actionTag { } - (void)remoteResponsFailed:(int)actionTag withMessage:(NSString *)message resultCode:(NSString *)code{ ShowTextMessage(message); [self cancelRefresh]; [self loadFailed]; } - (void)getContentOffset:(CGPoint)contentOffset { } #pragma mark - KVO call back - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (!self.tableView.userInteractionEnabled || self.tableView.alpha <= 0.01 || self.tableView.hidden) return; [self getContentOffset:self.tableView.contentOffset]; if (isFirstRefresh) { return; } if (isCanRefresh) { [self refreshMethod]; } if (isCanLoad) { [self loadMethod]; } } - (void)refreshMethod { if (self.tableView.contentOffset.y > 0) { [self cancelRefresh]; return; }; //向上滚出视区,return if (self.refreshHeader.state == RefreshStateRefreshing) { return; } self.refreshHeader.contentOffset = self.tableView.contentOffset; if (self.tableView.isDragging) { CGFloat normal2pullingOffsetY = 0-self.contentInsetTop-60.f; if (self.refreshHeader.state == RefreshStateNormal && self.tableView.contentOffset.y < normal2pullingOffsetY) { // 转为即将刷新状态 self.refreshHeader.state = RefreshStatePulling; } else if (self.refreshHeader.state == RefreshStatePulling && self.tableView.contentOffset.y >= normal2pullingOffsetY) { // 转为普通状态 self.refreshHeader.state = RefreshStateNormal; }else if (self.refreshHeader.state == RefreshStateNormal && self.tableView.contentOffset.y >= normal2pullingOffsetY) { // 转为即将刷新状态 self.refreshHeader.state = RefreshStateIsPulling; } }else { if (self.refreshHeader.state == RefreshStatePulling) { //松手转为刷新状态 [UIView animateWithDuration:0.2 animations:^{ self.tableView.contentInset = UIEdgeInsetsMake(self.contentInsetTop + 60, 0, 0, 0); }]; // 开始刷新 self.refreshHeader.state = RefreshStateRefreshing; } } } - (void)loadMethod { if (self.tableView.contentOffset.y < 0) { //顶部操作直接返回 return; } if (self.loadFooter.state == RefreshStateRefreshing || self.loadFooter.state == RefreshStateNoMore) { self.loadFooter.hidden = NO; return; } if (self.refreshHeader.state == RefreshStateRefreshing) { return; } CGPoint offset = self.tableView.contentOffset; CGRect bounds = self.tableView.bounds; CGSize size = self.tableView.contentSize; UIEdgeInsets inset = self.tableView.contentInset; CGFloat currentOffset = offset.y + bounds.size.height - inset.bottom; CGFloat maximumOffset = size.height; CGFloat compareOffset = currentOffset - maximumOffset; if (self.tableView.isDragging ) { if (compareOffset<15 ) { if (!self.tableView.isDecelerating) { self.loadFooter.state = RefreshStateNormal; } }else if (self.loadFooter.state == RefreshStateNormal && (currentOffset - maximumOffset)>20) { self.loadFooter.hidden = NO; if (!self.tableView.isDecelerating) { self.loadFooter.state = RefreshStatePulling; //转为即将刷新 }else { self.loadFooter.state = RefreshStateRefreshing; } } }else { self.loadFooter.hidden = NO; if (self.loadFooter.state == RefreshStatePulling) { self.loadFooter.state = RefreshStateRefreshing; }else { self.loadFooter.state = RefreshStateNormal; } } } - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { UIMenuController *menu = [UIMenuController sharedMenuController]; if (menu.menuVisible) { [menu setMenuVisible:NO animated:YES]; return; } } //- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { // // if (scrollView.contentOffset.y == 0) { // return; // } // // if (scrollView.contentOffset.y+scrollView.frame.size.height+1<scrollView.contentSize.height) { // return; // } // //// NSLog(@"scrollView.contentSize.height:%f ,scrollView.contentOffset.y:%f, scrollView.height:%f",scrollView.contentSize.height,scrollView.contentOffset.y,scrollView.frame.size.height); // // if (scrollView.contentOffset.y > 0 && self.canFooterRefresh) { // if (self.loadFooter.state == RefreshStateNormal) { // self.loadFooter.state = RefreshStateRefreshing; // } // } //} - (void)dealloc { if (isCanRefresh || isCanLoad) { [self removeObserver:self forKeyPath:@"self.tableView.contentOffset"]; } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } /* #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