IOS控件系列二---优雅的UITableView的MVC模式设计,支持自定义下拉刷新/上提加载更多视图(含swift)

来源:互联网 发布:java访问https 编辑:程序博客网 时间:2024/06/05 06:46


demo效果如下:










本小框架设计原则依旧按照之前的惯例:

1.扩展性好,代码不冗余(整个刷新的头部与底部代码不超过300行)。

2.逻辑清晰。

3.回调接口清晰。

4.移植性好。


对于扩展性本框架扩展点如下:

1.框架中的BaseTableView是直接扩展UITableView的,所以可以使用在VC中,也可以作为其他视图的子视图进行使用,具体的使用demo可参看,之前的BossJob项目,各位看客可以在本博客中找。

BossJob项目链接

2.支持一个tableList中的展现不同的Cell同时支持不同的cell展现不同的高度。

3.支持上拉刷新视图与底部加载更多视图的自定义。


二逻辑部分:个人认为还是比较清晰的,如果发现其中逻辑不清晰的地方,在下恳请各位大神不要吝啬您的批评批评指点,博客本身就是一个交流的平台,共同学习进步才是王道。具体的设计思路如下:

1.超类直接重载UITabView 并将如下接口丢给子类去扩展。各接口有详细的注释,此处不重复了。

/** 初始化接口,子类重载时,可初始化自身的特有的对象 */-(void) initAttr;/** 构建单元格,子类需要重载此方法,方能达到效果 @return UITableViewCell */-(BaseTabViewCell*) buildTableViewCell;/** 获取单元格高度,子类需要重载 @return 单元格高度 */-(CGFloat) getCellHeight;/** 上提加载更多底部视图,子类需要扩展此类,不然后返回的底部加载更多视图是一个默认的视图 @return 返回一个扩展了ScrollViewRefreshView的具体子类 */-(ScrollViewRefreshView*) buildFootView;-(void(^)()) buildLoadMoreListener;/** 构建下拉刷新头部视图,子类需要扩展此类,不然后返回的下拉刷新视图是一个默认的视图 @return 返回一个扩展了ScrollViewHeadView的具体子类 *///-(ScrollViewHeadView*) buildHeadView;

对于展示不同的cell时需要重载

- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

能够显示不同的cell是在数据模型的基类中定义了一个枚举,各个数据模型均扩展这个数据基类,然后每个模型返回一个惟一的枚举。在上面的方法时,遍历当前行的单元格获取当前数据的枚举类型,再创建这个cell就可以达到效果。部分代码如下:

数据模型部分:

/** 构建UItableView cell的类型枚举 - QuickWordsType: 快捷消息类型 - QuickWordsType: 快捷消息增加类型 */typedef NS_ENUM(NSInteger, CellItemType) {        CellItemDefaultType = 1,    QuickWordsType,    QuickWordsAddType,    };/** 数据类型协议接口,通常用于同一个tableView中展示不同的item类型 */@protocol ItemType <NSObject>@optional-(CellItemType) getItemType;@end/** 列表中的基类接口 */@interface BaseModel : NSObject<ItemType>@property(nonatomic,weak) id<ItemType> delegate;@property(nonatomic,copy) NSString* name;@end

重写如下方法显示不同的cell:

//重写此方法,达到一个列表中展现不同的cell- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {            BaseModel *baseModel = self.dataList[indexPath.row];    BaseTabViewCell *cell;    NSString *cellIdentifier;        switch ([baseModel getItemType]) {        case ChatHeadType:            cellIdentifier = @"ChatHeadType";            break;        case ChatType:            cellIdentifier = @"ChatType";            break;        default:            break;    }        cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];        if (!cell) {        switch ([baseModel getItemType]) {            case ChatHeadType:                cell = [[ChatHeadCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];                break;            case ChatType:                cell = [[ChatCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];                break;            default:                break;        }    }        [cell bindData:baseModel];    return cell;}

因为不同的cell的高度可能不一致,所以还需要重载如下方法:

//重写此方法达到不同的cell有不同的高度-(CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{        BaseModel *baseModel = self.dataList[indexPath.row];    CGFloat height = 0.0f;        switch ([baseModel getItemType]) {                    case ChatHeadType:            height = 40.0f;            break;                    case ChatType:            height = 70.0f;            break;                    default:            break;    }    return height;}

上面所陈述的内容涵盖了数据模型层 、控制器层、视图层。各位看官请自行分辨。


三。下拉刷新/上提加载更多视图核心设计思路:

监听UIScrollView的contentOffset 用以实现头部或底部视图的插入位置 ,

监听UIScrollView的contentSize用来更新底部加载更多视图的位置 ,因为内容的增长是从上往下增长的,即从0--n位置增长,不然会造成底加载更多视图位置的错乱。而头部永远数据前面的位置。所以不需要担心位置发生错乱。

本框架封装了基类,并将添加的接口封装到的BaseTableView基类中方便子类扩展,在本DEMO中提供了2种使用方式,一种是将视图接口,封装到BaseTableView,另一种是封装到具体的UItableView中,即哪一个列表需要使用上拉/下拉功能,就使用这个接口。


四。回调接口部分,使用block,具体见代码。 


先看控制器层的代码,详细代码如下:

basetableView.h:

#import <UIKit/UIKit.h>#import "ScrollViewRefreshView.h"#import "ScrollViewHeadView.h"@class BaseTabViewCell;@class BaseRefreshHeadView;/** 消息页面,列表基类 */@interface BaseTableView : UITableView<UITableViewDataSource,UITableViewDelegate,CAAnimationDelegate>@property(nonatomic,strong)UITableView* mTableView;@property(nonatomic,strong)NSMutableArray *dataList;@property(nonatomic,assign) BOOL bIsRefreshing;@property(nonatomic,assign) BOOL bIsLoading;@property(nonatomic,strong) ScrollViewRefreshView* scrollFootView;@property(nonatomic,strong) ScrollViewHeadView* scrollHeadView;/** 初始化接口,子类重载时,可初始化自身的特有的对象 */-(void) initAttr;/** 构建单元格,子类需要重载此方法,方能达到效果 @return UITableViewCell */-(BaseTabViewCell*) buildTableViewCell;/** 获取单元格高度,子类需要重载 @return 单元格高度 */-(CGFloat) getCellHeight;/** 上提加载更多底部视图,子类需要扩展此类,不然后返回的底部加载更多视图是一个默认的视图 @return 返回一个扩展了ScrollViewRefreshView的具体子类 */-(ScrollViewRefreshView*) buildFootView;-(void(^)()) buildLoadMoreListener;/** 构建下拉刷新头部视图,子类需要扩展此类,不然后返回的下拉刷新视图是一个默认的视图 @return 返回一个扩展了ScrollViewHeadView的具体子类 *///-(ScrollViewHeadView*) buildHeadView;@end

baseTableView.m:

#import "BaseTableView.h"#import "Constants.h"#import "BaseModel.h"#import "BaseTabViewCell.h"#import "BaseRefreshHeadView.h"@implementation BaseTableView-(instancetype) initWithFrame:(CGRect)frame{    if(self = [super initWithFrame:frame]){            [self initAttr];        }    return self;}-(void) initAttr{    self.dataList = [NSMutableArray array];    self.backgroundColor = [UIColor colorWithRed:235.0 / 255.0 green:238.0/255.0 blue:237.0/255.0 alpha:1.0];    self.delegate = self;    self.dataSource = self;    [self reloadData];        [self addSubview:[self buildFootView]];    [[self buildFootView] loadMore:[self buildLoadMoreListener]];}-(BaseTabViewCell*) buildTableViewCell{    NSLog(@"这里必须重载");    return [[BaseTabViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"BaseTabViewCell"];;}-(CGFloat) getCellHeight{    return 0.0f;}#pragma mark - UITableView delegate- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {        return [self.dataList count];}- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {            BaseTabViewCell* cell = [self buildTableViewCell];        [cell setFrame:CGRectMake(0, 0, SCREEN_WIDTH, [self getCellHeight])];        cell.backgroundColor = [UIColor colorWithRed:235.0 / 255.0 green:238.0/255.0 blue:237.0/255.0 alpha:1.0];        BaseModel* data = ((BaseModel* )self.dataList[indexPath.row]);        [cell bindData:data];    return cell;    }- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {        [tableView deselectRowAtIndexPath:indexPath animated:YES];        }- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {        return [self getCellHeight];}//-------------------uitableView 协议方法结束------------------------(ScrollViewRefreshView*) buildFootView{    if(!self.scrollFootView){        self.scrollFootView = [[ScrollViewRefreshView alloc] initWithFrame:self.frame];        [self.scrollFootView addTargetWith:self];    }    return self.scrollFootView;}-(void(^)()) buildLoadMoreListener{    LoadMoreBlock loadMore = ^(){                        double delayTime = 3.0;        dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, delayTime * NSEC_PER_SEC);        dispatch_after(time, dispatch_get_main_queue(), ^{                        [self buildFootView].loadMoreState = LoadMoreNoMoreData;        });    };        return loadMore;}@end


视图层的代码:

.baseTableViewcell.h


#import <UIKit/UIKit.h>@class BaseModel;/** 列表中基类单元格,所有的单元均需扩展此类 */@interface BaseTabViewCell : UITableViewCell-(void) initItemView;-(void) bindData:(BaseModel*_Nonnull) data;/** 此接口为回收资源接口,子类需要扩展 */-(void) recycRes;@end

basetableViewcell.m

#import "BaseTabViewCell.h"#import "BaseModel.h"@implementation BaseTabViewCell//留给子类类扩展-(void) initItemView{}//留给子类类扩展-(void) bindData:(BaseModel*_Nonnull) data{    }//回收资源接口-(void) recycRes{    NSLog(@"看到此日志信息,说明你已经考滤的很全面了,不过还需要加油^_^");}@end



数据层的代码为:

BaseModel.h

#import <UIKit/UIKit.h>/** 构建UItableView cell的类型枚举 - QuickWordsType: 快捷消息类型 - QuickWordsType: 快捷消息增加类型 */typedef NS_ENUM(NSInteger, CellItemType) {        CellItemDefaultType = 1,    QuickWordsType,    QuickWordsAddType,    };/** 数据类型协议接口,通常用于同一个tableView中展示不同的item类型 */@protocol ItemType <NSObject>@optional-(CellItemType) getItemType;@end/** 列表中的基类接口 */@interface BaseModel : NSObject<ItemType>@property(nonatomic,weak) id<ItemType> delegate;@property(nonatomic,copy) NSString* name;@end


baseMOdel.m


#import "BaseModel.h"@interface BaseModel ()@end@implementation BaseModel-(instancetype) init{    if(self = [super init]){            self.delegate = self;    }    return self;}//override 协议接口-(CellItemType) getItemType{    return CellItemDefaultType;}@end



 上提加载更多视图的代码,名字没取好:请自行忽略名字怪异大笑大笑大笑,对于本视图,本demo中设置一些状态枚举,用来控制刷新的表现过程。

#import <UIKit/UIKit.h>typedef NS_ENUM(NSInteger,LoadMore){        LoadMoreLoading = 1,    LoadMoreComplete,    LoadMoreNoMoreData,    };typedef void(^LoadMoreBlock)(void);/** 滚动列表中下拉刷新/上提加载更多的公共刷新视图 */@interface ScrollViewRefreshView : UIView@property(nonatomic,assign) LoadMore loadMoreState;/** 初始View布局与全局属性 */-(void) initView;/** 将当前视图绑定到滚动列表中 @param scrollView 目标滚动列表 */-(void) addTargetWith:(UIScrollView* ) scrollView;/** *  上提加载更多回调接口 *  @param block 加载更多 block */- (void)loadMore:(void(^)())block;/** 加载更多完成接口 */-(void) loadMoreComplete;@end

.m文件:

#import "ScrollViewRefreshView.h"#import "Constants.h"#define kRefreshViewWidth  200#define kRefreshViewHeight 80#define kMaxPullUpDistance   84#define MarginForLoadMore  60       //用来控制,上提多少point才调用加载更多接口@interface ScrollViewRefreshView ()@property (nonatomic, strong) UIScrollView *scrollView;@property (nonatomic, assign) CGSize contentSize;@property (nonatomic, copy) LoadMoreBlock loadMoreBlock;@property(nonatomic,strong) UILabel* labelRefresh;@end@implementation ScrollViewRefreshView-(instancetype) initWithFrame:(CGRect)frame{        self = [super initWithFrame:CGRectMake(0,CGRectGetHeight(frame), SCREEN_WIDTH, kRefreshViewHeight)];        if(self){            }    return self;}-(void) initView{            self.labelRefresh = [[UILabel alloc] initWithFrame:CGRectMake(20, 0, self.frame.size.width, 40)];    self.labelRefresh.text = @"上提加载更多";    self.labelRefresh.backgroundColor = [UIColor greenColor];    [self insertSubview:self.labelRefresh atIndex:0];}-(void) addTargetWith:(UIScrollView* ) scrollView {        self.scrollView = scrollView;    [self.scrollView insertSubview:self atIndex:0];    [self.scrollView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];    [self.scrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];    self.hidden = NO;        self.labelRefresh = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, 40)];    self.labelRefresh.text = @"上提加载更多";    self.labelRefresh.textColor = [UIColor greenColor];    self.labelRefresh.textAlignment = NSTextAlignmentCenter;    self.labelRefresh.font = [UIFont systemFontOfSize:12.0];    [self insertSubview:self.labelRefresh atIndex:0];            //延迟 0.2s更新位置,防止位置被遮挡    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 0.2 * NSEC_PER_SEC);    dispatch_after(time, dispatch_get_main_queue(), ^{        self.center = CGPointMake(self.center.x, self.contentSize.height + kRefreshViewHeight/2);    });}- (void)loadMore:(void (^)())block{    self.loadMoreBlock = block;}-(void)loadMoreComplete{    self.loadMoreState  = LoadMoreComplete;    self.center = CGPointMake(self.center.x, self.contentSize.height + kRefreshViewHeight/2);}//override method-(void) setLoadMoreState:(LoadMore)loadMoreState{        if(_loadMoreState != loadMoreState){             _loadMoreState = loadMoreState;    }    switch(_loadMoreState){            case LoadMoreLoading:{            self.labelRefresh.text = @"正在加载,请稍后...";                    }break;                    case LoadMoreComplete:{                    self.labelRefresh.text = @"上提加载更多";                    }break;        case LoadMoreNoMoreData:{                        self.labelRefresh.text = @"---HAPPY END----";                }break;        }}#pragma mark - KVO- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {        if ([keyPath isEqualToString:@"contentSize"]) {        self.contentSize = [[change valueForKey:NSKeyValueChangeNewKey] CGSizeValue];        if (self.contentSize.height >= CGRectGetHeight(self.scrollView.frame)) {            self.hidden = NO;        }        self.center = CGPointMake(self.center.x, self.contentSize.height + kRefreshViewHeight/2); //防止下拉刷新时,位置显示不对的情况    }        if ([keyPath isEqualToString:@"contentOffset"]) {                if(self.loadMoreState == LoadMoreLoading || self.loadMoreState == LoadMoreNoMoreData) return;                CGPoint contentOffset = [[change valueForKey:NSKeyValueChangeNewKey] CGPointValue];                if (contentOffset.y >= MarginForLoadMore) {                        if (!self.scrollView.tracking ) {                self.hidden = NO;                self.center = CGPointMake(self.center.x, self.contentSize.height + kRefreshViewHeight/2);                self.loadMoreState = LoadMoreLoading;                self.scrollView.contentInset = UIEdgeInsetsMake(0, 0, self.labelRefresh.frame.size.height, 0);                if (self.loadMoreBlock) {                    self.loadMoreBlock();                }            }                    }    }}#pragma mark - dealloc- (void)dealloc {    [self.scrollView removeObserver:self forKeyPath:@"contentOffset"];    [self.scrollView removeObserver:self forKeyPath:@"contentSize"];}@end

 下拉刷新视图:


#import <UIKit/UIKit.h>typedef NS_ENUM(NSInteger,PullDownRefresh){        PullDownRefreshNomral = 1,    PullDownRefreshing,    PullDownRefreshComplete,    };typedef void(^PullDownRefreshBlock)(void);/** ScrollView列表的下拉刷新视图 */@interface ScrollViewHeadView : UIView@property (nonatomic, strong) UIScrollView *scrollView;//@property (nonatomic, assign) CGFloat originOffset;@property (nonatomic, assign) CGFloat progress;@property (nonatomic, assign) BOOL isLoading;@property (nonatomic, assign) BOOL notTracking;@property(nonatomic,strong) UILabel* labelRefresh;@property (nonatomic, copy) PullDownRefreshBlock refreshingBlock;@property(nonatomic,assign) PullDownRefresh refershState;/** 将当前视图绑定到滚动列表中  @param scrollView 目标滚动列表 */-(void) addTargetWith:(UIScrollView* ) scrollView;/** *  上提加载更多回调接口 *  @param bolck 下拉刷新 block */- (void) refresh:(PullDownRefreshBlock) bolck;/** 加载更多完成接口 */-(void) refreshComplete;@end


.m文件:


#import "ScrollViewHeadView.h"#import "Constants.h"#define kRefreshViewWidth  200#define kRefreshViewHeight 80#define kMaxPullDownDistance   84#define MarginForRefrshing  60       //用来控制,上提多少point才调用加载更多接口@implementation ScrollViewHeadView-(instancetype) initWithFrame:(CGRect)frame{        self = [super initWithFrame:CGRectMake(0,-kRefreshViewHeight,SCREEN_WIDTH, kRefreshViewHeight)];    if(self){            }    return self;    }-(void) addTargetWith:(UIScrollView* ) scrollView {            // self.originOffset = 70.0;        self.scrollView = scrollView;    [self.scrollView insertSubview:self atIndex:0];    [self.scrollView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];       //self.backgroundColor = [UIColor yellowColor];        self.labelRefresh = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, kRefreshViewHeight)];    self.labelRefresh.text = @"下拉刷新数据";    self.labelRefresh.textColor = [UIColor greenColor];    self.labelRefresh.textAlignment = NSTextAlignmentCenter;    self.labelRefresh.font = [UIFont systemFontOfSize:12.0];    [self insertSubview:self.labelRefresh atIndex:0];        //    //延迟 0.2s更新位置,防止位置被遮挡//    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 0.2 * NSEC_PER_SEC);//    dispatch_after(time, dispatch_get_main_queue(), ^{//        self.center = CGPointMake(self.center.x, self.contentSize.height + kRefreshViewHeight/2);//    });}//override --method-(void) setRefershState:(PullDownRefresh)refershState{        if(_refershState != refershState){            _refershState = refershState;    }        switch(_refershState){                    case PullDownRefreshNomral:{                        self.labelRefresh.text = @"下拉刷新数据";                }break;            case PullDownRefreshing:{                        self.labelRefresh.text = @"正在刷新,请稍后...";                }break;                                case PullDownRefreshComplete:{                        self.labelRefresh.text = @"刷新完成";                }break;        }}-(void) refresh:(PullDownRefreshBlock)bolck{    self.refreshingBlock = bolck;}-(void) refreshComplete{    self.refershState = PullDownRefreshNomral;    self.scrollView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);}#pragma mark - KVO- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {    if ([keyPath isEqualToString:@"contentOffset"]) {                if(self.refershState == PullDownRefreshing) return;                CGPoint contentOffset = [[change valueForKey:NSKeyValueChangeNewKey] CGPointValue];        if (MarginForRefrshing + contentOffset.y <= 0) {                        if (!self.scrollView.tracking) {                                self.refershState = PullDownRefreshing;                self.scrollView.contentInset = UIEdgeInsetsMake(kMaxPullDownDistance, 0, 0, 0);                                if (self.refreshingBlock) {                    self.refreshingBlock();                }            }        }    }}#pragma mark - dealloc- (void)dealloc {    [self.scrollView removeObserver:self forKeyPath:@"contentOffset"];}@end


demo源码:github  劳驾留下您的星星与评论,谢谢


swift版本为oc的翻译版本,。。。。。


tab;eView相关的文件:

import Foundationimport UIKitclass BaseTableView : UITableView,UITableViewDelegate,UITableViewDataSource{            var dataList:Array<BaseModel>?            override init(frame: CGRect, style: UITableViewStyle) {        super.init(frame: frame, style: style)        self.frame = frame        initAttr()    }        required init?(coder aDecoder: NSCoder) {        fatalError("init(coder:) has not been implemented")    }        func initAttr(){                self.dataList = Array()        self.dataSource = self        self.delegate = self            }            /// 获取单元格高度--子类需要重载    ///    /// - Returns: 单元格高度    func getCellHeight() -> CGFloat {                return 70.0    }            /// 构建单元格视图子类需重载,不然显示默认视图    ///    /// - Returns: 单元格视图    func buildTableViewCell() -> BaseTabViewCell {        print("子类赶紧支重载吧,不然单元格是默认视图")               return BaseTabViewCell.init(style: UITableViewCellStyle.default, reuseIdentifier: "BaseCell")            }        //implements protocol    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {                return (dataList?.count)!    }            //implements protocol    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {                return getCellHeight()    }        //implements protocol    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {                let cell = buildTableViewCell()                cell.frame = CGRect(x : 0, y : 0, width : self.frame.width, height : self.getCellHeight())                        let data :BaseModel = (dataList?[indexPath.row])!                cell.bindData(data: data)                return cell        }        }

import Foundationimport UIKitclass QuickWordsView: BaseTableView {            //    init(style: UITableViewStyle, reuseIdentifier: String){//        //super.init(reuseIdentifier:reuseIdentifier,style:style)//        //    }//    //    required init?(coder aDecoder: NSCoder) {//        fatalError("init(coder:) has not been implemented")//    }        override func initAttr() {                super.initAttr()                        self.backgroundColor = UIColor.init(red: 235.0 / 255.0, green:238.0/255.0, blue:237.0/255.0, alpha:1.0)                let wrods:[String] = ["能同时开发android/ios","我可以把简历发您看看么?",                               "我能去贵司面试么?","对不起,贵司提供的职位可能不太适合,谢谢"]                for item in wrods{                    let model : QuickWordsModel = QuickWordsModel()                        model.name = item                        self.dataList?.append(model)        }                        //添加底部加载更多视图        let scrollFootView : ScrollViewRefreshView = ScrollViewRefreshView.init(frame: self.frame)        scrollFootView.addTargetWith(scrollView: self)                scrollFootView.loadMore = {() ->Void in                    if((self.dataList?.count)! > 10){                            scrollFootView.setLoadMoreState(loadMoreState: LoadMoreType.LoadMoreNoMoreData)                return            }                                    DispatchQueue.main.asyncAfter(deadline:DispatchTime.now() + Double(Int64(3 *  Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)){                                for i in 0 ..< 3{                                    let model:QuickWordsModel = QuickWordsModel()                                        model.name = String.init(format: "loadmore data %d", i)                                        self.dataList?.append(model)                }                                self.reloadData()                                scrollFootView.loadMoreComplete()                            }        }                //添加头部刷新视图        let scrollHeadView : ScrollViewHeadView = ScrollViewHeadView.init(frame: self.frame)        scrollHeadView.addTargetWith(scrollView: self)        scrollHeadView.refrsh(block:{()->Void in                    DispatchQueue.main.asyncAfter(deadline:DispatchTime.now() + Double(Int64(3 *  Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)){                                self.dataList?.removeAll()                                for i in 0 ..< 1{                                        let model:QuickWordsModel = QuickWordsModel()                                        model.name = String.init(format: "refresh data %d", i)                                        self.dataList?.append(model)                }                                self.reloadData()                                scrollHeadView.refreshComplete()                            }                    })            }            override func buildTableViewCell() -> BaseTabViewCell {        return QiuckWordsCell(style:UITableViewCellStyle.default, reuseIdentifier : "QiuckWordsCell")    }        override func getCellHeight() -> CGFloat {                return 40.0    }}



tableViewCell相关文件 ,先上基类文件:

import Foundationimport UIKit/// UItableView 中的单元格基类  所有的单元格均需要重载本灰class BaseTabViewCell: UITableViewCell {            var label:UILabel?        override init(style: UITableViewCellStyle, reuseIdentifier: String?) {        super.init(style: style, reuseIdentifier: reuseIdentifier)                initItemView()    }        required init?(coder aDecoder: NSCoder) {        fatalError("init(coder:) has not been implemented")    }        /// 子类需要重载本接口    func initItemView() {                label = UILabel(frame:CGRect(x : 10.0 , y : self.center.y, width : 80, height:30))                label?.text = "韦小宝"                label?.font = UIFont.systemFont(ofSize: 14)                self.addSubview(label!)            }                /// 将数据模型与单元格绑定起来,子类需要重载本接口    ///    /// - Parameter data: <#data description#>    func bindData(data:BaseModel){            }            /// 回收资源接口,子类必要时重载    func recycRes(){    }    }



具体的单元格:

import Foundationimport UIKitclass QiuckWordsCell: BaseTabViewCell {        var labelWords:UILabel?        var data:QuickWordsModel?            override func initItemView() {            self.backgroundColor = UIColor.clear                labelWords = UILabel(frame:CGRect(x : 10.0 , y : 0, width : self.frame.width, height:30))        labelWords?.textAlignment = NSTextAlignment.center        labelWords?.text = "韦小宝"                labelWords?.font = UIFont.systemFont(ofSize: 14)                self.addSubview(labelWords!)    }        override func bindData(data: BaseModel) {                if self.data != data {                        self.data = data as? QuickWordsModel            labelWords?.text = self.data?.name        }    }}



数据框架类:


import Foundationenum CellItemType {        case DefaultType        case QuickWordsType        case QuickWordsAddType    }/// 单元格对应的数据类型接口protocol ItemType {        func getItemType() -> CellItemType}class BaseModel : NSObject,ItemType{    var name:String = "defalue name"        var delegate: ItemType?        override init() {        super.init()                self.delegate = self    }        //implement ItemType interface    func getItemType() -> CellItemType {                return CellItemType.DefaultType    }    }


具体的数据模型:

import Foundationclass QuickWordsModel: BaseModel {            override func getItemType() -> CellItemType {                return CellItemType.QuickWordsType    }}


在viewController中使用使用


import UIKitclass ViewController: UIViewController {    override func viewDidLoad() {        super.viewDidLoad()                test()        }        func test() {                let qwv: QuickWordsView = QuickWordsView.init(frame:CGRect(x : 0, y : 50,width: self.view.frame.width, height: 400))        qwv.initAttr()        qwv.separatorInset = UIEdgeInsetsMake(0, 10, 0, 10)        qwv.tableFooterView = UIView(frame:CGRect.zero)                self.view.addSubview(qwv)    }    override func didReceiveMemoryWarning() {        super.didReceiveMemoryWarning()        // Dispose of any resources that can be recreated.    }}




阅读全文
0 0
原创粉丝点击