一、使用原理:scrollView
1、AppDelegate.h
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate,UITableViewDataSource,UITableViewDelegate,UIScrollViewDelegate>
{
BOOL _isDraging;//判断目前是否正在拉,如果正在拉还想拉就会无效
}
@property (strong, nonatomic) UIWindow *window;
@property(nonatomic,retain)NSMutableArray *dataArr;
@end
2、AppDelegate.m
#import "AppDelegate.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.backgroundColor = [UIColor whiteColor];
self.dataArr = [NSMutableArray arrayWithCapacity:0];
_isDraging = NO;//初始化这个状态为NO,没有开拽
[self makeUI];
[self loadData];
[self.window makeKeyAndVisible];
return YES;
}
-(void)makeUI
{
UITableView *table = [[UITableView alloc] initWithFrame:CGRectMake(0, 64, 320, self.window.frame.size.height-64) style:UITableViewStylePlain];
table.dataSource = self;
table.delegate = self;
[self.window addSubview:table];
[table release];
table.tag = 6666;
//原理一、我们拽出来的东西在table的上面再向上和下面再向下藏着,不拽不出来
UIView *upView = [[UIView alloc] initWithFrame:CGRectMake(0, -self.window.frame.size.height, 320, self.window.frame.size.height)];
upView.backgroundColor = [UIColor redColor];
[table addSubview:upView];
UILabel *lab = [[UILabel alloc] initWithFrame:CGRectMake(0, self.window.frame.size.height-30, 320, 30)];
lab.text = @"正在拽,拽拽拽拽拽拽拽拽";
[upView addSubview:lab];
[lab release];
[upView release];
}
-(void)loadData
{
int num = self.dataArr.count;
for(int i = num;i<num+20;i++)
{
[self.dataArr addObject:[NSString stringWithFormat:@"第%d行",i]];
}
UITableView *table = (UITableView*)[self.window viewWithTag:6666];
[table reloadData];
//原理三,在卡住执行完这个方法后,要解除卡住,归位,还得把bool值设为NO
_isDraging = NO;
table.contentInset = UIEdgeInsetsZero;//归位,zero就是四个0
//设置table的cell滚到那儿
if(self.dataArr.count>20)//刷过一次
{
[table scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self.dataArr.count-1-20 inSection:0] atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
//设置table的cell滚到哪行
//第一个参数是滚到哪儿,里面有行和段组成
//第二个参数是滚到哪儿的那个哪儿,停在哪儿
//第三个参数是要不要动画
}
}
//原理二,拽的原理就是找到滚动视图的某一个点,达到这个点之后,就先卡住,开始做点事儿,做完了再解除卡住的状态
//想要即时找到滚动视图滚到那儿了,就要用scrollView的DidScroll代理方法,在这个代理方法中,参数就是正在被拽的那个scrollView或者他的子类对象
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if(!_isDraging)
{//NO的时候进
//判断现在滚到哪儿了
//table?scrollView参数
if(scrollView.contentOffset.y < -50)//判断是不是滚到一个节点了,目前设置的是下拽能不能拽过50
{//拽过50进
//说明到达临界点了,即将开始卡住
_isDraging = YES;//开拽了
//把table卡住
scrollView.contentInset = UIEdgeInsetsMake(50, 0, 0, 0);
//实际上,这里该发起网络请求
//我们这里用一个延迟方法模拟请求两秒后的状态
[self performSelector:@selector(loadData) withObject:nil afterDelay:5];
//第一个参数是一会儿要调用的方法
//第二个参数是可能的参数
//第三个参数是延迟的秒数
}
}
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.dataArr.count;
}
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *str = @"ss";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:str];
if(cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:str] autorelease];
}
cell.textLabel.text = self.dataArr[indexPath.row];
return cell;
}
二、系统原生方法:只有下拉
1、AppDelegate.h
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate,UITableViewDataSource,UITableViewDelegate>
{
UIRefreshControl *_refreshControl;//系统下拉
}
@property (strong, nonatomic) UIWindow *window;
@property(nonatomic,retain)NSMutableArray *dataArr;
@end
2、AppDelegate.m
#import "AppDelegate.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.backgroundColor = [UIColor whiteColor];
self.dataArr = [NSMutableArray arrayWithCapacity:0];
[self makeUI];
[self loadData];
[self.window makeKeyAndVisible];
return YES;
}
-(void)makeUI
{
UITableView *table = [[UITableView alloc] initWithFrame:self.window.bounds style:UITableViewStylePlain];
table.dataSource = self;
table.delegate = self;
[self.window addSubview:table];
[table release];
table.tag = 6666;
//设置系统刷新控件
_refreshControl = [[UIRefreshControl alloc] init];
_refreshControl.tintColor = [UIColor blueColor];//上面颜色
[table addSubview:_refreshControl];
[_refreshControl release];
NSAttributedString *str = [[NSAttributedString alloc] initWithString:@"正在努力加载中..."];
_refreshControl.attributedTitle = str;//设置上面文字
[str release];
//给这个refresh添加个方法
[_refreshControl addTarget:self action:@selector(refreshWorking:) forControlEvents:UIControlEventValueChanged];
}
-(void)refreshWorking:(UIRefreshControl*)refreshControl
{
//正常应该去请求
[self performSelector:@selector(loadData) withObject:nil afterDelay:5];
}
-(void)loadData
{
int num = self.dataArr.count;
for(int i = num;i<num+20;i++)
{
[self.dataArr addObject:[NSString stringWithFormat:@"第%d个",i]];
}
UITableView *table = (UITableView*)[self.window viewWithTag:6666];
[table reloadData];
//让下拉的玩意儿回去
[_refreshControl endRefreshing];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.dataArr.count;
}
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *str = @"ss";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:str];
if(cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:str] autorelease];
}
cell.textLabel.text = self.dataArr[indexPath.row];
return cell;
}
三、EGO:使用最广,最烂
1、AppDelegate.h
#import <UIKit/UIKit.h>
#import "EGORefreshTableHeaderView.h"//ego的下拉
#import "EGORefreshTableFooterView.h"//ego的上拉
@interface AppDelegate : UIResponder <UIApplicationDelegate,UITableViewDataSource,UITableViewDelegate,EGORefreshTableDelegate,UIScrollViewDelegate>//四个协议,两个table,一个ego,一个scroll
{
EGORefreshTableHeaderView *_refreshHeadView;//下拉对象
EGORefreshTableFooterView *_refreshFootView;//上拉对象
BOOL isRefresh;//判断是下拉还是上拉
BOOL _reloading;//判断是否正在刷新,如果正在刷新,那么再次刷新无效
}
@property(nonatomic,retain)NSMutableArray *dataArr;
@property (strong, nonatomic) UIWindow *window;
@end
2、AppDelegate.m
#import "AppDelegate.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
-(void)dealloc
{
self.dataArr = nil;
[super dealloc];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.backgroundColor = [UIColor whiteColor];
self.dataArr = [NSMutableArray arrayWithCapacity:0];
[self makeUI];
[self loadData];
[self.window makeKeyAndVisible];
return YES;
}
-(void)makeUI
{
UITableView *table = [[UITableView alloc] initWithFrame:self.window.bounds style:UITableViewStylePlain];
table.dataSource = self;
table.delegate = self;
[self.window addSubview:table];
[table release];
table.tag = 6666;
[self creatHeaderView];//调用创建下拉视图的方法
}
-(void)loadData
{
int num = self.dataArr.count;
for(int i = num;i<num+20;i++)
{
[self.dataArr addObject:[NSString stringWithFormat:@"第%d个",i]];
}
UITableView *table = (UITableView*)[self.window viewWithTag:6666];
[table reloadData];
}
#pragma mark table 代理
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.dataArr.count;
}
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *dd = @"dd";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:dd];
if(cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:dd] autorelease];
}
cell.textLabel.text = self.dataArr[indexPath.row];
return cell;
}
#pragma mark 设计实例化EGO的header和footer
//header,做一个header,贴在table的顶上再向上-的位置,不拉不出来
-(void)creatHeaderView//添加下拉刷新的视图
{
if(_refreshHeadView && [_refreshHeadView superview])//当有head且有父视图时
{
[_refreshHeadView removeFromSuperview];//移除headView,防止重复添加headView
}
_refreshHeadView = [[EGORefreshTableHeaderView alloc] initWithFrame:CGRectMake(0, 0-self.window.frame.size.height, self.window.frame.size.width, self.window.bounds.size.height)];//Y值为负的
_refreshHeadView.delegate = self;//设置ego的代理
UITableView *tab = (UITableView*)[self.window viewWithTag:6666];
[tab addSubview:_refreshHeadView];//把header贴到table上
[_refreshHeadView refreshLastUpdatedDate];//修改最后一次刷新的时间,如果写了这个方法,那么必须实现ego的时间代理方法
}
//footer,做一个footer,贴在table的content内容视图的下边,table只有已经滚到底儿的时候再拉,才能拉出来
-(void)setFootView
{
UITableView *tab = (UITableView*)[self.window viewWithTag:6666];
CGFloat height = MAX(tab.contentSize.height, tab.frame.size.height);//比较出来更高的
//MAX比较数字大小
if(_refreshFootView && [_refreshFootView superview])//判断有没有,贴没贴
{//如果有且贴了的话,刷新上拉footer的位置(YYYYYYY)
_refreshFootView.frame = CGRectMake(0, height, tab.frame.size.width, self.window.bounds.size.height);//当footView已存在的时候,直接修改他的位置
}
else
{//如果没有footer,实例化一个新的footer,并且新的footer的Y也是算出来大的那个数
_refreshFootView = [[EGORefreshTableFooterView alloc] initWithFrame:CGRectMake(0, height, tab.frame.size.width, self.window.bounds.size.height)];//没有footView的时候,创建
_refreshFootView.delegate = self;
[tab addSubview:_refreshFootView];
}
if(_refreshFootView)
{
[_refreshFootView refreshLastUpdatedDate];//刷新最后一次的时间
}
}
#pragma mark scrollView的代理
//滚动调用
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
//边滚变做foot(边滚边改变foot的位置)
[self setFootView];
if(_refreshHeadView)//判断正滚的是footer还是header
{
[_refreshHeadView egoRefreshScrollViewDidScroll:scrollView];//判断是否达到节点位置
}
if(_refreshFootView)
{
[_refreshFootView egoRefreshScrollViewDidScroll:scrollView];//判断是否达到节点位置
}
}
//松手调用
-(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
//松手时,如果没达到节点高度,那么table直接归位,如果达到节点高度了,卡住开始刷新
if(_refreshHeadView)
{
[_refreshHeadView egoRefreshScrollViewDidEndDragging:scrollView];//让EGO判断是否达到节点了,如果达到节点了,就调用EGO的刷新代理
}
if(_refreshFootView)
{
[_refreshFootView egoRefreshScrollViewDidEndDragging:scrollView];//让EGO判断是否达到节点了,如果达到节点了,就调用EGO的刷新代理
}
}
#pragma mark EGO的代理
//ego开始工作的代理
-(void)egoRefreshTableDidTriggerRefresh:(EGORefreshPos)aRefreshPos
{
[self beginToReloadData:aRefreshPos];//开始工作
}
//刷新ego是否在工作的状态,bool值,ego内部会根据这个bool值判断拉了之后是否要工作,如果已经在工作状态,拉了也白拉,如果NO,则开始工作
-(BOOL)egoRefreshTableDataSourceIsLoading:(UIView *)view
{
return _reloading;
}
//刷新ego的最后一个时间
-(NSDate*)egoRefreshTableDataSourceLastUpdated:(UIView *)view
{
return [NSDate date];
}
#pragma ego工作代码,这里是咱们自己发挥的地方,在这儿可以发起网络请求之类的数据操作
//下面这个方法在ego工作代理方法中被调用
-(void)beginToReloadData:(EGORefreshPos)refreshPos
{
_reloading = YES;//设置工作状态为yes,yes后再拉就没用了
//判断正在拉的是下拉还是上拉,分别进行不同的工作
if(refreshPos == EGORefreshHeader)
{//下拉进来,执行刷新方法
[self refreshView];//当是下拉刷新的时候,我们刷新view
}
else if (refreshPos == EGORefreshFooter)
{//上拉进来,执行看下一页的方法
[self getNextPageView];//当时上拉加载的时候,我们获取新的额外数据并刷新view
}
}
-(void)refreshView//下拉刷新
{
[self performSelector:@selector(finishReloadingDataRefresh) withObject:nil afterDelay:3];
}
-(void)getNextPageView//上拉加载
{
[self performSelector:@selector(finishReloadingDataGetMore) withObject:nil afterDelay:3];
}
-(void)finishReloadingDataRefresh//下拉调用的方法
{
//下拉干点啥
//下拉之后不管已经有几百条数据了,把数据全删了,获取最新的前20条数据,刷新UI
[self.dataArr removeAllObjects];//清空
for(int i = 0;i<20;i++)
{
[self.dataArr addObject:[NSString stringWithFormat:@"第%d个",i]];
}
//这之后数据源里只有前20条了
//实际在这里清空数据源后,我们应该发起这个页面的请求,请求第一个page的数据
//刷新UI
UITableView *table = (UITableView*)[self.window viewWithTag:6666];
[table reloadData];
//因为是下拉,所以让header通知结束,table归位
[_refreshHeadView egoRefreshScrollViewDataSourceDidFinishedLoading:table];
//不管上拉下拉,都要改变bool值
_reloading = NO;
}
-(void)finishReloadingDataGetMore//上拉调用的方法
{
//上拉干点啥
[self loadData];//增加20条数据
//刷新UI
UITableView *table = (UITableView*)[self.window viewWithTag:6666];
[table reloadData];
//刷新完了table,table就增加了20行,这个时候table的新的contentSize就定下来
//把footer的位置在变一下,向下走20行
[self setFootView];
//因为是上拉,所以让footer通知刷新结束
[_refreshFootView egoRefreshScrollViewDataSourceDidFinishedLoading:table];
//不管上拉下拉,都要改变bool值
_reloading = NO;
}
四、MJ:超简单,常用
1、AppDelegate.h
#import <UIKit/UIKit.h>
#import "MJRefresh.h"
@interface AppDelegate : UIResponder <UIApplicationDelegate,UITableViewDataSource,UITableViewDelegate,MJRefreshBaseViewDelegate>
{
MJRefreshHeaderView *_header;//下拉
MJRefreshFooterView *_footer;//上拉
}
@property (strong, nonatomic) UIWindow *window;
@property(nonatomic,retain)NSMutableArray *dataArr;
@end
2、AppDelegate.m
#import "AppDelegate.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
-(void)dealloc
{
[_header free];//这个非常重要,一定不能忘了写
[_footer free];//这个非常重要,一定不能忘了写
self.dataArr = nil;
[super dealloc];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.backgroundColor = [UIColor whiteColor];
self.dataArr = [NSMutableArray arrayWithCapacity:0];
[self makeUI];
[self loadData];
[self.window makeKeyAndVisible];
return YES;
}
-(void)makeUI
{
UITableView *table = [[UITableView alloc] initWithFrame:self.window.bounds style:UITableViewStylePlain];
table.dataSource = self;
table.delegate = self;
[self.window addSubview:table];
[table release];
table.tag = 6666;
//准备MJ的下拉和上拉
//下拉
_header = [MJRefreshHeaderView header];
_header.scrollView = table;//设置下拉的对应滚动视图,下拉给谁用
_header.delegate = self;
//上拉
_footer = [MJRefreshFooterView footer];
_footer.scrollView = table;
_footer.delegate = self;
[_header beginRefreshing];//head下拉初始化一次
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.dataArr.count;
}
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *str = @"ss";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:str];
if(cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:str] autorelease];
}
cell.textLabel.text = self.dataArr[indexPath.row];
return cell;
}
-(void)loadData
{
int num = self.dataArr.count;
for(int i = num;i<num+20;i++)
{
[self.dataArr addObject:[NSString stringWithFormat:@"第%d个",i]];
}
UITableView *table = (UITableView*)[self.window viewWithTag:6666];
[table reloadData];
}
//MJ的代理方法,拉到节点了就调这个
-(void)refreshViewBeginRefreshing:(MJRefreshBaseView *)refreshView
{
if(refreshView == _header)
{//下拉进
[self performSelector:@selector(refresh:) withObject:refreshView afterDelay:3];
}
else
{//上拉进
[self performSelector:@selector(getMore:) withObject:refreshView afterDelay:3];
}
}
-(void)refresh:(MJRefreshBaseView*)refreshView//下拉的干点啥
{
[self.dataArr removeAllObjects];//清空
[self loadData];
//告诉MJ完了
[refreshView endRefreshing];
}
-(void)getMore:(MJRefreshBaseView*)refreshView//上拉的干点啥
{
[self loadData];
//告诉MJ完了
[refreshView endRefreshing];
}
五、Get和Post异步请求分装
1、NetWork.h
#import <Foundation/Foundation.h>
@protocol NetWorkDelegate <NSObject>
-(void)sendBackMessage:(id)object;//把我们请求到的东西当成参数传回去
@end
@interface NetWork : NSObject<NSURLConnectionDataDelegate>
@property(nonatomic,retain)NSMutableData *data;
@property(nonatomic,assign)id<NetWorkDelegate>delegate;
-(void)initWithURL:(NSString*)url andInterface:(NSString*)interface andKeyArr:(NSArray*)keyArr andValueArr:(NSArray*)valueArr andType:(BOOL)isGet;
@end
2、NetWork.m
#import "NetWork.h"
@implementation NetWork
-(void)dealloc
{
self.data = nil;
[super dealloc];
}
//这个方法只能被对象调用,在这里就是self
-(void)initWithURL:(NSString *)url andInterface:(NSString *)interface andKeyArr:(NSArray *)keyArr andValueArr:(NSArray *)valueArr andType:(BOOL)isGet
{
NSString *urlStr = url;
NSString *interfaceStr = interface;
NSArray *keyArrHere = keyArr;
NSArray *valueArrHere = valueArr;
NSMutableString *reqStr = [NSMutableString stringWithCapacity:0];
NSMutableString *objectStr = [NSMutableString stringWithCapacity:0];
if(isGet)
{
[reqStr appendFormat:@"%@%@?",urlStr,interfaceStr];
for(int i = 0;i<keyArrHere.count;i++)
{
[reqStr appendFormat:@"%@=%@",keyArrHere[i],valueArrHere[i]];
if(i<keyArr.count-1)
{
[reqStr appendString:@"&"];
}
}
}
else
{//post
[reqStr appendFormat:@"%@%@",urlStr,interfaceStr];
for(int i = 0;i<keyArr.count;i++)
{
[objectStr appendFormat:@"%@=%@",keyArr[i],valueArr[i]];
if(i<keyArr.count-1)
{
[objectStr appendString:@"&"];
}
}
}
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:reqStr] cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:10];
if(!isGet)
{//post
[req setHTTPMethod:@"POST"];
[req setHTTPBody:[objectStr dataUsingEncoding:NSUTF8StringEncoding]];
}
NSURLConnection *con = [NSURLConnection connectionWithRequest:req delegate:self];
[con start];
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
[self.delegate sendBackMessage:@"失败了"];
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[self.data appendData:data];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
id temp = [NSJSONSerialization JSONObjectWithData:self.data options:NSJSONReadingMutableLeaves error:nil];
[self.delegate sendBackMessage:temp];
}
@end