IOS开发笔记iOS Developer编程知识点

IOS UI篇-仿微博下拉刷新和上拉加载

2017-03-08  本文已影响710人  Bob_Blog

前言

效果图

效果图.gif

应用知识点

加载进父视图时,注册观察者,实时监听UIScrollView的contentOffset的变化,根据变化展示不一样的刷新状态,执行相应的操作。

pragma mark -加入父视图时添加观察者
- (void)willMoveToSuperview:(UIView *)newSuperview {
    [super willMoveToSuperview:newSuperview];
    if (newSuperview) {
        self.superScrollview = (UIScrollView *)newSuperview;
        [self.superScrollview addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil];
    }else {
        if (self.superScrollview) {
            [self.superScrollview removeObserver:self forKeyPath:@"contentOffset"];
            
        }
    }
}
#pragma mark-KVO的代理方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
    if ([keyPath isEqualToString:@"contentOffset"]) {
  
        if (self.superScrollview.contentInset.top==64) {
            
            self.contentOffSetY=self.superScrollview.contentInset.top;
        }
        CGFloat y = self.superScrollview.contentOffset.y;
        if (self.superScrollview.isDragging) {
            //正在拖动
            
            if (y<  -self.contentOffSetY &&y> -self.contentOffSetY - headerRefeshHight && self.currentState ==TBStatuePulling) {
                //下拉状态->正常状态
                self.currentState = TBStatueNomal;
                
            }else if (y <= -self.contentOffSetY - headerRefeshHight && self.currentState == TBStatueNomal)
                //正常状态->下拉状态
            {
                self.currentState = TBStatuePulling;
            }
        }else if(self.currentState ==TBStatuePulling &&y <= -self.contentOffSetY - headerRefeshHight){ //拖拽释放
            self.currentState = TBStatueRefreshing;
        }

    }
}
.h文件
@class TBRefreshHeadView;

@class TBRefreshFootView;

@interface UIScrollView (TBRefresh)
//下拉刷新
@property(nonatomic,weak)TBRefreshHeadView *header;
//上拉加载
@property(nonatomic,weak)TBRefreshFootView *footer;

//添加下拉刷新方法
-(void)addRefreshHeaderWithBlock:(void (^)())Block;

//添加上拉刷新方法
-(void)addRefreshFootWithBlock:(void (^)())Block;
.m文件
#pragma mark-关联头部
-(void)setHeader:(TBRefreshHeadView *)header
{
    
   objc_setAssociatedObject(self, @selector(header), header, OBJC_ASSOCIATION_ASSIGN);
    
}

-(TBRefreshHeadView*)header
{
     return objc_getAssociatedObject(self, @selector(header));
}


#pragma mark-关联底部
-(void)setFooter:(TBRefreshFootView *)footer
{
    
    objc_setAssociatedObject(self, @selector(footer), footer, OBJC_ASSOCIATION_ASSIGN);
    
}

-(TBRefreshFootView*)footer
{
    
    return objc_getAssociatedObject(self, @selector(footer));
    
}

#pragma mark-初始化头部
-(void)addRefreshHeaderWithBlock:(void (^)())Block
{
    TBRefreshHeadView *TBheader=[TBRefreshHeadView new];
    
    TBheader.ReturnBlock=Block;
    
    self.header=TBheader;
    
    [self insertSubview:TBheader atIndex:0];
    
}

#pragma mark-初始化底部
-(void)addRefreshFootWithBlock:(void (^)())Block
{
    
    TBRefreshFootView *TBfooter=[TBRefreshFootView new];
    
    TBfooter.ReturnBlock=Block;
    
    self.footer=TBfooter;
    
    [self insertSubview:TBfooter atIndex:0];

}

调用

刷新头

//开始下拉刷新
-(void)beginRefreshing;

//结束下拉刷新
-(void)endHeadRefresh;

加载底部

//结束下拉加载
- (void)endFooterRefreshing;

//没有更多数据
-(void)NoMoreData;

//将没有更多数据状态设置为正常状态
-(void)ResetNomoreData;

使用

-(UITableView*)mainTableview
{
    if (!_mainTableview) {
    
        __weak ViewController *weakself=self;
        _mainTableview=[[UITableView alloc]initWithFrame:CGRectMake(0,0, self.view.frame.size.width, self.view.frame.size.height) style:UITableViewStylePlain];
        
        _mainTableview.delegate=self;
        
        _mainTableview.dataSource=self;
        
        [_mainTableview addRefreshHeaderWithBlock:^{
          
            [weakself LoadDatas];
            
        }];
        
        [_mainTableview addRefreshFootWithBlock:^{
          
            [weakself LoadMoreDatas];
        }];
   
    }
    return _mainTableview;
}

注意:移除观察者

移除观察者的时候,发现tableview是先于刷新头和刷新尾释放的,所以在tableView调用dealloc方法时,先将移除观察者,然后将刷新头和刷新尾置nil,发现dealloc方法会调用2次,查了资料发现。一次是 scrollView(实际tableView),另一次是UITableViewWrapperView,这个类是我们直接使用的。这种情况会出现在tableView上。scrollView 和 collectionView 不会出现,所以我做了以下处理:

#pragma mark-测试可得,tableView先释放,所以在释放之前把头部和尾部释放,移除观察者,不然会奔溃
-(void)dealloc
{
    if (self.header) {
        [self removeObserver:self.header forKeyPath:@"contentOffset"];
        self.header=nil;
    }
    
    if (self.footer) {
        [self removeObserver:self.footer forKeyPath:@"contentOffset"];
        
        self.footer=nil;
    }
}

最后

这个我第一篇简书,写的不好,大家多多指教!
附上github地址demo地址,ios 路还长,学习的很多,以后会继续下去!
参考资料:

上一篇下一篇

猜你喜欢

热点阅读