为期两天的网易新闻简单完成,其中还有许多模糊的点,在此发文:
- 一是为了自己总结思路以及再次贯彻一下整个小demo的细节操作
- 二是回顾一下比较遗忘容易忽略的知识点
- 三是为了激励自己的开发兴趣,顺便分享给大家,共同享受iOS所带来的开发乐趣吧
示例demo:(ps:最后做分类模块字体滑动有个阴影bug 有懂得大牛求帮忙解决感谢感谢)
好咯,接下来就开始我的实现之路吧~
####第一步:环境的配置(cocoaPods安装指南)
#安装CocoaPods
### 查看当前的源
sudo gem sources -l
### 添加源
sudo gem sources -a https://ruby.taobao.org/
### 删除源
sudo gem sources -r https://rubygems.org/
### 安装
sudo gem install cocoapods
pod setup
***
#使用CocoaPods
### 搜索
pod search AFNetworking
### 生成 Podfile
echo "pod 'AFNetworking'" > Podfile
### 安装
pod install
### 升级
pod update
由于本demo为抓包获取网易新闻的JSON 我所采用的是第三方框架 异步下载网络图片也是使用它自带的UIImage的分类
-
第一步:自定义工具类获取单例对象(继承与AFHTTPSessionManager)
#import "HMNetworkTools.h"
@implementation HMNetworkTools
+ (instancetype)sharedNetworkTools{
static HMNetworkTools *instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{NSURL *baseURL = [NSURL URLWithString:@"http://c.m.163.com/nc/"]; NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; //配置超时时长 config.timeoutIntervalForRequest = 30; instance = [[self alloc]initWithBaseURL:baseURL sessionConfiguration:config]; }); //设置转换模式 instance.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/html",@"text/json", @"text/javascript", nil]; return instance; } @end
-
第二步:实现的就是图片轮播器的那个效果
监听网易新闻发送的HTTP请求,获取请求数据的地址.根据获取的数据创建图片轮播器使用的模型类HeadLine
创建模型类,设置需要的属性
封装网络操作
Controller中加载数据测试
自定义cell显示图片
#import
@interface HMHeadLine : NSObject
//定义属性
@property (nonatomic,copy)NSString *title;
@property (nonatomic,copy)NSString *imgsrc;
+ (instancetype)headlineWithDict:(NSDictionary *)dict;
//放松异步请求获取数据
+ (void)headlineWithSucess:(void(^)(NSArray *array))sucess error:(void(^)())error;
@end
异步发送请求获取模型对象
#import "HMHeadLine.h"
#import "HMNetworkTools.h"
@implementation HMHeadLine
+ (instancetype)headlineWithDict:(NSDictionary *)dict{
HMHeadLine *headline = [self new];
[headline setValuesForKeysWithDictionary:dict];
return headline;
}
- (void)setValue:(id)value forUndefinedKey:(NSString *)key{
}
//获取数据
+ (void)headlineWithSucess:(void (^)(NSArray *))sucess error:(void (^)())error{
[[HMNetworkTools sharedNetworkTools] GET:@"ad/headline/0-4.html" parameters:nil success:^(NSURLSessionDataTask *task, NSDictionary *responseObject) {
//字典转模型获取数据
//获取第一个KEY
NSString *rootKey = responseObject.keyEnumerator.nextObject;
NSArray *array = responseObject[rootKey];
NSMutableArray *marray = [NSMutableArray arrayWithCapacity:4];
//循环遍历获取模型
[array enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
HMHeadLine *model = [HMHeadLine headlineWithDict:obj];
[marray addObject:model];
}];
if (sucess) {
sucess(marray.copy);
}
} failure:^(NSURLSessionDataTask *task, NSError *error) {
if (error) {
}
}];
}
@end
自定义cell
#import "HMHeadlineCell.h"
#import "HMHeadLine.h"
#import
@interface HMHeadlineCell ()
@property (weak, nonatomic) IBOutlet UIImageView *imgsrcView;
@property (weak, nonatomic) IBOutlet UILabel *titleView;
@property (weak, nonatomic) IBOutlet UIPageControl *pageControl;
@end
@implementation HMHeadlineCell
//从写headline的方法
- (void)setHeadline:(HMHeadLine *)headline{
_headline = headline;
//解决重用问题
self.imgsrcView.image = nil;
self.titleView.text = nil;
//设置图片
[self.imgsrcView setImageWithURL:[NSURL URLWithString:headline.imgsrc]];
//设置标题
self.titleView.text = headline.title;
self.pageControl.currentPage = self.tag;
}
@end
自定义CollectionViewControllView控制器实现数据源方法 加载数据实现图片轮播器的效果
#import "HMImageLoopController.h"
#import "HMHeadLine.h"
#import "HMHeadlineCell.h"
@interface HMImageLoopController ()
@property (weak, nonatomic) IBOutlet UICollectionViewFlowLayout *flowLaout;
//当前图片的索引
@property (nonatomic, assign) NSInteger currentIndex;
//声明一个属性
@property (nonatomic,strong)NSArray *array;
@end
@implementation HMImageLoopController
- (void)viewDidLoad {
[super viewDidLoad];
//设置背景颜色
self.collectionView.backgroundColor = [UIColor whiteColor];
[HMHeadLine headlineWithSucess:^(NSArray *array) {
self.array = array;
} error:^{
NSLog(@"请求数据失败");
}];
[self setCollectionViewStyle];
}
#pragma mark - 刷新数据
- (void)setArray:(NSArray *)array{
_array = array;
[self.collectionView reloadData];
//永远显示第二个CELL
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:1 inSection:0];
[self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:0 animated:NO];
}
- (void)viewDidLayoutSubviews{
[super viewDidLayoutSubviews];
//设置cell的大小
self.flowLaout.itemSize = self.collectionView.frame.size;
}
#pragma mark - 设置collectionView的样式
- (void)setCollectionViewStyle{
//设置滚动方向
self.flowLaout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
self.flowLaout.minimumInteritemSpacing = 0;
self.flowLaout.minimumLineSpacing = 0;
self.collectionView.bounces = NO;
self.collectionView.pagingEnabled = YES;
self.collectionView.showsHorizontalScrollIndicator = NO;
}
#pragma mark - 数据源方法
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return self.array.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
//创建cell
HMHeadlineCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"headline" forIndexPath:indexPath];
//在滚动过程中下一张图片的索引
//当滚动的过程中item的值可能是 0 或者 2
NSInteger index = (self.currentIndex + indexPath.item - 1 + self.array.count) % self.array.count;
cell.backgroundColor = [UIColor whiteColor];
cell.headline = self.array[index];
cell.tag = index;
return cell;
}
//collectionView的代理方法
//滚动停止之后,把cell换成第二个cell
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
//计算下一张图片的索引 (+1 -1)
//返回的值始终是 (0 2) - 1
int offset = scrollView.contentOffset.x / scrollView.bounds.size.width - 1;
self.currentIndex = (self.currentIndex + offset + self.array.count ) % self.array.count;
//始终显示第二个cell
//主队列的执行特点:先等待主线程上的代码都执行完毕,再执行队列中的任务
dispatch_async(dispatch_get_main_queue(), ^{
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:1 inSection:0];
[self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:0 animated:NO];
});
}
@end
第三步:实现新闻列表模块-实现数据的显示及刷新数据(图文混排效果,单图,大图,及三张图片显示的效果)
- 利用containerView 将图片轮播器加载到一个自定义tabelView上形成联动
同理- 创建新闻列表模型对象,发送异步请求获取数据,自定义tabelViewControllerView控制器及自定义cell加载数据
- 创建模型
#import
@interface HMNews : NSObject
//声明属性
@property (nonatomic,copy)NSString *imgsrc;
@property (nonatomic,copy)NSString *digest;
@property (nonatomic,copy)NSNumber *replyCount;
@property (nonatomic,copy)NSString *title;
//声明一个大图属性
@property (nonatomic,assign)BOOL imgType;
//声明三张图的属性
@property (nonatomic, copy) NSArray *imgextra;
//定义方法
+ (instancetype)newsWithDict:(NSDictionary *)dict;
//发送异步请求获取数据
+ (void)newsWithurlString:(NSString *)urlString Sucess:(void(^)(NSArray *array))sucessBlock error:(void(^)())errorBlock;
@end
- 封装并且回调实现异步发送请求获取数据
#import "HMNews.h"
#import "HMNetworkTools.h"
@implementation HMNews
+ (instancetype)newsWithDict:(NSDictionary *)dict{
HMNews *news = [HMNews new];
[news setValuesForKeysWithDictionary:dict];
return news;
}
- (void)setValue:(id)value forUndefinedKey:(NSString *)key{
}
//发送异步请求获取数据
+ (void)newsWithurlString:(NSString *)urlString Sucess:(void(^)(NSArray *array))sucessBlock error:(void(^)())errorBlock{
[[HMNetworkTools sharedNetworkTools] GET:urlString parameters:nil success:^(NSURLSessionDataTask *task, NSDictionary *responseObject) {
//获取KEY
NSString *rootKey = responseObject.keyEnumerator.nextObject;
//获取数组
NSArray *array = responseObject[rootKey];
NSMutableArray *mArray = [NSMutableArray arrayWithCapacity:10];
//遍历数组获取模型
[array enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
HMNews *model = [HMNews newsWithDict:obj];
[mArray addObject:model];
}];
if (sucessBlock) {
sucessBlock(mArray.copy);
}
} failure:^(NSURLSessionDataTask *task, NSError *error) {
if (errorBlock) {
errorBlock();
}
}];
}
@end
-
自定义cell 实现新闻列表中所要求格式的新闻详情列表
#import
@class HMNews; @interface HMNewsCell : UITableViewCell //定义属性属性 @property (nonatomic,strong)HMNews *news; //判断是否为大图cell + (NSString *)getReuseId:(HMNews *)news; //判断行高 + (CGFloat)getRowHeight:(HMNews *)news; @end -
实现自定义cell中的属性赋值并且判断图片要求格式的要求进行图片选择
#import "HMNewsCell.h" #import "HMNews.h" #import
@interface HMNewsCell () //声明图片,文字,摘要及回复数 @property (weak, nonatomic) IBOutlet UIImageView *imgsrcView; @property (weak, nonatomic) IBOutlet UILabel *titleView; @property (weak, nonatomic) IBOutlet UILabel *digestView; @property (weak, nonatomic) IBOutlet UILabel *replyCount; @property (strong, nonatomic) IBOutletCollection(UIImageView) NSArray *imgextraViews; @end @implementation HMNewsCell //从写news的set方法进行赋值 - (void)setNews:(HMNews *)news{ _news = news; //获取图片,文字,摘要及回复数 [self.imgsrcView setImageWithURL:[NSURL URLWithString:news.imgsrc]]; self.titleView.text = news.title; self.digestView.text = news.digest; self.replyCount.text = [NSString stringWithFormat:@"回帖数:%d",news.replyCount.intValue]; //获取数组中的照片 [news.imgextra enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { //获取图片的路径 NSString *imgsrc = obj[@"imgsrc"]; UIImageView *imageView = self.imgextraViews[idx]; [imageView setImageWithURL:[NSURL URLWithString:imgsrc]]; }]; } //判断是否为大图cell + (NSString *)getReuseId:(HMNews *)news{ if (news.imgType) { //大图 return @"news1"; }else if(news.imgextra){ //三张图 return @"news2"; } return @"news"; } //判断行高 + (CGFloat)getRowHeight:(HMNews *)news{ if (news.imgType) { //大图 return 200; }else if (news.imgextra){ //三张图 return 150; } return 80; } @end -
在自定义控制器中实现请求并且实现他的数据源方法 实现新闻列表的数据展示
#import "HMNewsController.h"
#import "HMNews.h"
#import "HMNewsCell.h"
@interface HMNewsController ()//定义一个属性 @property (nonatomic,strong)NSArray *array; @end @implementation HMNewsController - (void)viewDidLoad { [super viewDidLoad]; } - (void)setUrlString:(NSString *)urlString{ //防止cell重用问题 self.array = nil; [HMNews newsWithurlString:urlString Sucess:^(NSArray *array) { //获取数据 self.array = array; } error:^{ NSLog(@"出错"); }]; } #pragma mark - 异步操作刷新数据 - (void)setArray:(NSArray *)array{ _array = array; [self.tableView reloadData]; } #pragma mark - 数据源方法 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.array.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { //1.获取数据 HMNews *news = self.array[indexPath.row]; //2.创建cell HMNewsCell *cell = [tableView dequeueReusableCellWithIdentifier:[HMNewsCell getReuseId:news]]; cell.news = news; return cell; } #pragma mark - 判断cell的行高 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ //1.获取数据 HMNews *news = self.array[indexPath.row]; return [HMNewsCell getRowHeight:news]; } @end
第四部:(PS:也是最为困难的一步:至今虽然代码敲出来了 但是还是觉得很晕这里面就涉及到了控制器之间的关联又能显示滚动翻页又要实现分类之间的滑动最重要就是数据的分类刷新---希望有大牛能帮我解释一番)
老样子 现在要实现的是就是把之前写的代码都整合在一起放在一个自定义UIViewControllView中,设置根控制器为NavcontrollViewContrllView 在里面自控制器加入一个高度为44的scrollvIew及一个占下面的CollectView用来接受上面的两个自定义类的数据 在根据JSON中的tname及tid 进行分类传值刷新获取不同新闻的列表 以及自定义的lbael的滚动.
在此-我会从写创建一个StrobBord用来设置页面到时候会从这里传回数据
-
这里所需要的模型数据就是从网易新闻的抓包获取的资源JSON用来管理不同新闻的分类.
#import
@interface HMChannel : NSObject //新闻的分类(频道) @property (nonatomic,copy)NSString *tname; @property (nonatomic,copy)NSString *tid; //获取请求数据网址 @property (nonatomic,copy,readonly)NSString *urlString; + (instancetype)channelWithDict:(NSDictionary *)dict; //返回数组懒加载 + (NSArray *)channelWithArray; @end -
懒加载数据获取模型对象 并且实现网址的传输
#import "HMChannel.h"@implementation HMChannel + (instancetype)channelWithDict:(NSDictionary *)dict{ HMChannel *channel = [self new]; [channel setValuesForKeysWithDictionary:dict]; return channel; } - (void)setValue:(id)value forUndefinedKey:(NSString *)key{ } //返回数组懒加载 + (NSArray *)channelWithArray{ //从本地加载数据 NSString *path = [[NSBundle mainBundle] pathForResource:@"topic_news.json" ofType:nil]; NSData *data = [NSData dataWithContentsOfFile:path]; //JSON的反序列化 NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL]; NSArray *array = dict[@"tList"]; NSMutableArray *mArray = [NSMutableArray arrayWithCapacity:10]; //遍历数据 字典转模型 [array enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { HMChannel *model = [HMChannel channelWithDict:obj]; [mArray addObject:model]; }]; //对模型中的tid进行排序 return [mArray sortedArrayUsingComparator:^NSComparisonResult(HMChannel *obj1, HMChannel *obj2) { return [obj1.tid compare:obj2.tid]; }]; } //获取网络地址 - (NSString *)urlString{ return [NSString stringWithFormat:@"article/headline/%@/0-140.html",self.tid]; } @end
自定义cell 在collectionView中实现NEWS stroboard 添加view 实现他的数据源方法 从新获取新闻数据
-
Home.storyboard中collectionView的每一个cell都要去加载News.storyboard中的view,所以创建自定义cell。
#import "HMHomeCell.h"
#import "HMNewsController.h"@interface HMHomeCell () @property (nonatomic,strong)HMNewsController *newsController; @end @implementation HMHomeCell //获取数据 - (void)awakeFromNib{ //创建控制器加载View UIStoryboard *sb= [UIStoryboard storyboardWithName:@"News" bundle:nil]; self.newsController = [sb instantiateInitialViewController]; [self.contentView addSubview:self.newsController.view]; } //设置view的大小 - (void)layoutSubviews{ [super layoutSubviews]; self.newsController.view.frame = self.bounds; } - (void)setUrlString:(NSString *)urlString{ self.newsController.urlString = urlString; } @end
-
自定义lbl实现 滚动分类的实现(并且实现新闻频道的标签的缩放及位置的变化)
#define kBIGFONT 18 #define kSMALLFONT 14 #import "HMChannelLabel.h" @implementation HMChannelLabel + (instancetype)channelLabelWithTName:(NSString *)tname{ HMChannelLabel *lbl = [self new]; lbl.text = tname; lbl.textAlignment = NSTextAlignmentCenter; //设置lbl大小 lbl.font = [UIFont systemFontOfSize:kBIGFONT]; [lbl sizeToFit]; //lbl默认大小 lbl.font = [UIFont systemFontOfSize:kSMALLFONT]; return lbl; } - (void)setScale:(CGFloat)scale{ CGFloat max = kBIGFONT * 1.0 / kSMALLFONT - 1; self.transform = CGAffineTransformMakeScale( max*scale+1, max*scale+1); self.textColor = [UIColor colorWithRed:scale green:0 blue:0 alpha:1]; } @end
PS 最后一步 就是实现整个新闻的大致排版 也就是实现数据的加载跟lbl的创建及新闻频道分类滚动实现(lbl计算涉及数学运算比较多~ 不作为本项目的重点)但是不知道lbl滚动为什么会有阴影的出现 有哪位大牛能够看错求忘能解决BUG,不胜感激.
#import "HMHomeController.h"
#import "HMChannel.h"
#import "HMChannelLabel.h"
#import "HMHomeCell.h"
@interface HMHomeController ()
//声明一个数组用来保存数据
@property (nonatomic,strong)NSArray *channels;
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (weak, nonatomic) IBOutlet UICollectionView *cooectionView;
@property (weak, nonatomic) IBOutlet UICollectionViewFlowLayout *flowLaout;
//记录当前lbl的的索引
@property (nonatomic,assign)int currenIndex;
@end
@implementation HMHomeController
#pragma mark - 懒加载
- (NSArray *)channels{
if (_channels == nil) {
_channels = [HMChannel channelWithArray];
}
return _channels;
}
- (void)viewDidLoad {
[super viewDidLoad];
//创建分类
[self loadChannels];
//设置item的大小及collettionView的属性
[self getCollectionView];
//加载新闻分类
[self loadChannels];
}
#pragma mark - 设置item的大小及collettionView的属性
- (void)getCollectionView{
//设置间距
self.flowLaout.minimumInteritemSpacing = 0;
self.flowLaout.minimumLineSpacing = 0;
self.flowLaout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
//设置collectionView一些属性
self.cooectionView.bounces = NO;
//分页
self.cooectionView.pagingEnabled = YES;
//水平条
self.cooectionView.showsHorizontalScrollIndicator = NO;
}
- (void)viewDidLayoutSubviews{
[super viewDidLayoutSubviews];
//设置cell大小
self.flowLaout.itemSize = self.cooectionView.frame.size;
}
#pragma mark - 创建频道中的分类
- (void)loadChannels{
//不让控制器自动生成64的偏移
self.automaticallyAdjustsScrollViewInsets = NO;
CGFloat marginX = 5;
CGFloat x = marginX;
CGFloat y = 0;
CGFloat h = self.scrollView.bounds.size.height;
//利用循环获取分类的名称
for (HMChannel *channel in self.channels) {
//自定义label获取数据
HMChannelLabel *lbl = [HMChannelLabel channelLabelWithTName:channel.tname];
//添加到scrollView中
[self.scrollView addSubview:lbl];
//设置frame 宽度就为字体本身的宽度
lbl.frame = CGRectMake(x, y, lbl.bounds.size.width, h);
x += lbl.bounds.size.width + marginX;
}
//scrollView滚动的范围
self.scrollView.contentSize = CGSizeMake(x, h);
//取消水平滑动条
self.scrollView.showsHorizontalScrollIndicator = NO;
HMChannelLabel *lbl = self.scrollView.subviews[0];
lbl.scale = 1;
}
#pragma mark - 寻找滚动时候下一个lbl
//当collectionView滚动时候计算lbl的顺序
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
//当前lbl
HMChannelLabel *currentlbl = self.scrollView.subviews[self.currenIndex];
//下一个lbl
HMChannelLabel *nextlbl = nil;
//遍历当前可见cell的索引
for (NSIndexPath *indexPath in self.cooectionView.indexPathsForVisibleItems) {
if (indexPath.item != self.currenIndex) {
//就是下一个lbl
nextlbl = self.scrollView.subviews[indexPath.item];
break;
}
if (nextlbl == nil) {
return;
}
}
//获取滚动的比例
CGFloat nextScale = ABS(scrollView.contentOffset.x / scrollView.bounds.size.width - self.currenIndex);
CGFloat currentScale = 1- nextScale;
currentlbl.scale = currentScale;
nextlbl.scale = nextScale;
//计算currentlbl的位置
self.currenIndex = scrollView.contentOffset.x / scrollView.bounds.size.width;
}
#pragma mark - 当滚动结束后计算currentlbl
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
//居中显示当前显示的标签
HMChannelLabel *label = self.scrollView.subviews[self.currenIndex];
CGFloat offset = label.center.x - self.scrollView.bounds.size.width * 0.5;
CGFloat maxOffset = self.scrollView.contentSize.width - label.bounds.size.width - self.scrollView.bounds.size.width;
if (offset < 0) {
offset = 0;
} else if (offset > maxOffset) {
offset = maxOffset + label.bounds.size.width;
}
[self.scrollView setContentOffset:CGPointMake(offset, 0) animated:YES];
}
#pragma mark - 数据源方法
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return self.channels.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
//获取数据
HMChannel *channel = self.channels[indexPath.item];
//创建cell
HMHomeCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"home" forIndexPath:indexPath];
cell.urlString = channel.urlString;
return cell;
}
@end
- PS 最后一步 就是实现整个新闻的大致排版 也就是实现数据的加载跟lbl的创建及新闻频道分类滚动实现(lbl计算涉及数学运算比较多~ 不作为本项目的重点)但是不知道lbl滚动为什么会有阴影的出现 有哪位大牛能够看错求忘能解决BUG,不胜感激.
由于第一次在上写项目 正如我开头说的那样 不求其他,只想对项目的整个思路再次贯穿一遍,顺便分享分享给各位书友们,学习之路任重道远,在乎是的对自己自身的要求跟习惯,只有在不断的前行之中发现自己的舍与得,希望大家在这条充满创新的道路上找到自己的那条殊途~
本人github地址:https://github.com/aryehToDog
iOS技术成长群:255032637 有愿意的小伙伴可以长期学习共勉!
2015.12.02