UI网络笔记(五):UI网络之上拉和下拉的四种方式

一、使用原理: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

    //设置tablecell滚到那儿

    if(self.dataArr.count>20)//刷过一次

    {

        [table scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self.dataArr.count-1-20 inSection:0] atScrollPosition:UITableViewScrollPositionMiddle animated:YES];

        //设置tablecell滚到哪行

        //第一个参数是滚到哪儿,里面有行和段组成

        //第二个参数是滚到哪儿的那个哪儿,停在哪儿

        //第三个参数是要不要动画

    }

}

//原理二,拽的原理就是找到滚动视图的某一个点,达到这个点之后,就先卡住,开始做点事儿,做完了再解除卡住的状态

//想要即时找到滚动视图滚到那儿了,就要用scrollViewDidScroll代理方法,在这个代理方法中,参数就是正在被拽的那个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 设计实例化EGOheaderfooter

//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,贴在tablecontent内容视图的下边,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,并且新的footerY也是算出来大的那个数

        _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;//设置工作状态为yesyes后再拉就没用了    

    //判断正在拉的是下拉还是上拉,分别进行不同的工作

    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];  

    //刷新完了tabletable就增加了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











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值