前言
开源高仿商城已经半年了,这半年基本上有时间的就在持续更新,收获了很多。从一开始随意的UI界面就这么实现,到开始copy国美商城再到这次更新基本上能说是高仿国美商城了。
之前有人问我怎么想起来开源高仿商城的,怎么开始 ?
-
我觉得首先大概浏览下要模仿APP的难易程度,从简单的地方先下手,写之前再多想想。
-
不要怕麻烦,再难的APP都会有很多简单的功能你可以去尝试,我最担心的就是怕出现难得不会做,简单不想做的死循环。
-
要敢于重构吧
商城的商品数据怎么办?
-
有一款非常值得推荐的软件 - Charles
-
不喜欢网络截取,也可以本地建Plist,或者利用数据库软件手动导入。
UI切图呢?
-
推荐两个icon网站 - iconstore、iconfont素材下载都是免费的
-
下载要模仿软件的
.ipa
之前是可以直接在iTunes
上下载,但是最新的版本中暂未发现此功能,可以下载旧版或者用助手软件归档出来。归档ipa
后查看包内容就可以查看素材了。
什么时候更新购车?
-
已列入后续实现规划,敬请期待。
tip:以上是我这近半年来开源项目的个人观点,希望能对你有所帮助~
本次更新主要更新了UI和增加了登录界面
-
高仿国美商城实现:
1.商城(商品分类,购物车,商品详情评论,筛选,属性回调,布局切换)
2.美媒榜(界面布局,父子控制器)
3.美店(界面布局)
4.我的(用户登录 账号:CDDMall 密码:000 可进入登录界面自行更改,界面布局)
-
预计后续实现功能
1.本地数据库的完善(个人信息,地址,购物车)
2.个人界面的信息更改(地址信息,用户信息)
3.立即购买后续开发
4.购物车界面的实现(逻辑)
5.扫一扫,搜索,等等小功能点的完善
GIF展示部分功能
实现
主要介绍这次更新功能。
-
登录TabBar拦截,以后成功后跳转
国美最新的登录思路是:在未登录的前提下,点击我的(个人中心)以及各项需登录后可查看的数据跳出登录界面,供用户点击登录。这里需特别说明:
① : 未登录在其他界面点击我的tabBar
presentViewController出登录界面
② : 输入账号密码登录后,登录界面dismissViewController后在要 ,切换到我的界面
③ :实现效果GIF
④ :实现思路遵循<UITabBarControllerDelegate>
的协议self.delegate = self;
实现其代理方法shouldSelectViewController
,在跳转控制器的时候做return
拦截。判断其登录成功后发通知跳转到我的登录状态下的界面。
-
代理
#pragma mark - 控制器跳转拦截
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
if(viewController == [tabBarController.viewControllers objectAtIndex:3]){
if (![[DCObjManager dc_readUserDataForKey:@"isLogin"] isEqualToString:@"1"]) {
DCLoginMeViewController *dcLoginVc = [DCLoginMeViewController new];
[self presentViewController:dcLoginVc animated:YES completion:nil];
return NO;
}
}
return YES;
}
-
通知
[self dismissViewControllerAnimated:YES completion:^{
[weakSelf.view endEditing:YES];
[[NSNotificationCenter defaultCenter]postNotificationName:LOGINSELECTCENTERINDEX object:nil];
}];
-
跳转到我的界面
WEAKSELF
[[NSNotificationCenter defaultCenter]addObserverForName:LOGINSELECTCENTERINDEX object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
weakSelf.tabBarController.selectedIndex = 3; //跳转到我的界面
}];
-
个人中心方法背景图的伸缩实现
① : 实现效果GIF
② : UITableView的tableHeaderView在初始化一个伸缩的UIImageView将其add到heaerView的最底层,并在代理方法中去实现图片的伸缩
- (UIImageView *)headerBgImageView{
if (!_headerBgImageView) {
_headerBgImageView = [[UIImageView alloc] init];
NSInteger armNum = [DCSpeedy dc_GetRandomNumber:1 to:9];
[_headerBgImageView setImage:[UIImage imageNamed:[NSString stringWithFormat:@"mine_main_bg_%zd",armNum]]];
[_headerBgImageView setBackgroundColor:[UIColor greenColor]];
[_headerBgImageView setContentMode:UIViewContentModeScaleAspectFill];
[_headerBgImageView setClipsToBounds:YES];
}
return _headerBgImageView;
}
[self.headView insertSubview:self.headerBgImageView atIndex:0]; //将背景图片放到最底层
#pragma mark - 滚动tableview 完毕之后
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
_topToolView.hidden = (scrollView.contentOffset.y < 0) ? YES : NO;
_topToolView.backgroundColor = (scrollView.contentOffset.y > 64) ? RGB(0, 0, 0) : [UIColor clearColor];
//图片宽高
CGFloat imageH = self.headView.dc_height;
CGFloat imageW = ScreenW;
//图片上下偏移量
CGFloat imageOffsetY = scrollView.contentOffset.y;
//上移
if (imageOffsetY < 0) {
CGFloat totalOffset = imageH + ABS(imageOffsetY);
CGFloat f = totalOffset / imageH;
self.headerBgImageView.frame = CGRectMake(-(imageW * f - imageW) * 0.5, imageOffsetY, imageW * f, totalOffset);
}
}
-
复杂的UI图分析,CollectionView实现布局
① : 实现效果GIF
② : 美店这个界面
-
我们首先隐藏Nav
#pragma mark - LifeCyle
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:YES animated:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self.navigationController setNavigationBarHidden:NO animated:animated];
}
-
加载自定义
DCBeautyTopToolView
,并在scrollViewDidScroll的代理方法中实现其隐藏和状态栏的状态更换
#pragma mark - 导航栏处理
- (void)setUpNavTopView
{
_topToolView = [[DCBeautyTopToolView alloc] initWithFrame:CGRectMake(0, 0, ScreenW, 64)];
_topToolView.leftItemClickBlock = ^{
NSLog(@"点击了我要开店");
};
_topToolView.rightItemClickBlock = ^{
NSLog(@"点击了消息");
};
[self.view addSubview:_topToolView];
}
#pragma mark - <UIScrollViewDelegate>
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
_topToolView.hidden = (scrollView.contentOffset.y < 0) ? YES : NO;
if (scrollView.contentOffset.y > DCNaviH) {
[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDefault;
[[NSNotificationCenter defaultCenter]postNotificationName:SHOWTOPTOOLVIEW object:nil];
}else{
[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;
[[NSNotificationCenter defaultCenter]postNotificationName:HIDETOPTOOLVIEW object:nil];
}
}
-
初始化UICollectionView,从布局来看,最上方的广告Slider、商品推荐和最美美店是横向布局,最后的热门话题是纵向布局。所以我分3组Section,除了热门话题我根据数据返回的数量,其余组Items为1
#pragma mark - <UICollectionViewDataSource>
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 3;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return (section == 2) ? _hotItem.count : 1 ;
}
-
在三组Section中在内嵌UICollectionView横向布局
UICollectionViewFlowLayout *dcFlowLayout = [UICollectionViewFlowLayout new];
dcFlowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
-
第二组Cell中
UIPageControl
需要更改它的大小和图片需要自定义重写
#pragma mark - 重写setCurrentPage方法更改PageControl的大小和图片
- (void)setCurrentPage:(NSInteger)page {
[super setCurrentPage:page];
for (NSUInteger subviewIndex = 0; subviewIndex < [self.subviews count]; subviewIndex++) {
UIImageView *subView = [self.subviews objectAtIndex:subviewIndex];
CGSize size;
size.height = 6;
size.width = 6;
[subView setFrame:CGRectMake(subView.frame.origin.x, subView.frame.origin.y,size.width,size.height)];
}
总结
总结一些开发中小技巧
一、在PCH中尽可能避免import
一些使用次数很少的文件;以及在类的文件中尽量少引用其他头文件,例如在如果需要引用一个类文件时,只是需要使用类名,不需要知道其中细节,可以用@class xxx.h
,两者的好处是减少一定的编译时间。
@class DCGridItem;
@interface DCGoodsGridCell : UICollectionViewCell
/* 10个属性数据 */
@property (strong , nonatomic)DCGridItem *gridItem;
二、在iOS开发中请尽量多使用const来代替宏定义参考,例如一些我定义一些Const(常量)文件来定义一些不对外公开的常量,Const不能满足的情况再考虑使用宏定义(#define)。
-
展示下项目中所遇到的通知
DCNotificationCenterName
DCNotificationCenterName.h
#pragma mark - 项目中所有通知
/** 登录成功选择控制器通知 */
UIKIT_EXTERN NSString *const LOGINSELECTCENTERINDEX;
/** 添加购物车或者立即购买通知 */
UIKIT_EXTERN NSString *const SELECTCARTORBUY;
/** 滚动到商品详情界面通知 */
UIKIT_EXTERN NSString *const SCROLLTODETAILSPAGE;
/** 滚动到商品评论界面通知 */
UIKIT_EXTERN NSString *const SCROLLTOCOMMENTSPAGE;
/** 展现顶部自定义工具条View通知 */
UIKIT_EXTERN NSString *const SHOWTOPTOOLVIEW;
/** 隐藏顶部自定义工具条View通知 */
UIKIT_EXTERN NSString *const HIDETOPTOOLVIEW;
/** 商品属性选择返回通知 */
UIKIT_EXTERN NSString *const SHOPITEMSELECTBACK;
/** 分享弹出通知 */
UIKIT_EXTERN NSString *const SHAREALTERVIEW;
DCNotificationCenterName.m
/** 登录成功选择控制器通知 */
NSString *const LOGINSELECTCENTERINDEX = @"LOGINSELECTCENTERINDEX";
/** 添加购物车或者立即购买通知 */
NSString *const SELECTCARTORBUY = @"SELECTCARTORBUY";
/** 滚动到商品详情界面通知 */
NSString *const SCROLLTODETAILSPAGE = @"SCROLLTODETAILSPAGE";
/** 滚动到商品评论界面通知 */
NSString *const SCROLLTOCOMMENTSPAGE = @"SCROLLTOCOMMENTSPAGE";
/** 展现顶部自定义工具条View通知 */
NSString *const SHOWTOPTOOLVIEW = @"SHOWTOPTOOLVIEW";
/** 隐藏顶部自定义工具条View通知 */
NSString *const HIDETOPTOOLVIEW = @"HIDETOPTOOLVIEW";
/** 商品属性选择返回通知 */
NSString *const SHOPITEMSELECTBACK = @"SHOPITEMSELECTBACK";
/** 分享弹出通知 */
NSString *const SHAREALTERVIEW= @"SHAREALTERVIEW";