高仿国美商城

前言

开源高仿商城已经半年了,这半年基本上有时间的就在持续更新,收获了很多。从一开始随意的UI界面就这么实现,到开始copy国美商城再到这次更新基本上能说是高仿国美商城了。

之前有人问我怎么想起来开源高仿商城的,怎么开始 ?

  • 我觉得首先大概浏览下要模仿APP的难易程度,从简单的地方先下手,写之前再多想想。
  • 不要怕麻烦,再难的APP都会有很多简单的功能你可以去尝试,我最担心的就是怕出现难得不会做,简单不想做的死循环。
  • 要敢于重构吧

商城的商品数据怎么办?

  • 有一款非常值得推荐的软件 - Charles
  • 不喜欢网络截取,也可以本地建Plist,或者利用数据库软件手动导入。

UI切图呢?

  • 推荐两个icon网站 - iconstoreiconfont素材下载都是免费的
  • 下载要模仿软件的.ipa之前是可以直接在iTunes上下载,但是最新的版本中暂未发现此功能,可以下载旧版或者用助手软件归档出来。归档ipa后查看包内容就可以查看素材了。
国美ipa

什么时候更新购车?

  • 已列入后续实现规划,敬请期待。
tip:以上是我这近半年来开源项目的个人观点,希望能对你有所帮助~

本次更新主要更新了UI和增加了登录界面

  • 高仿国美商城实现:

1.商城(商品分类,购物车,商品详情评论,筛选,属性回调,布局切换)

2.美媒榜(界面布局,父子控制器)

3.美店(界面布局)

4.我的(用户登录 账号:CDDMall 密码:000 可进入登录界面自行更改,界面布局)

  • 预计后续实现功能

1.本地数据库的完善(个人信息,地址,购物车)

2.个人界面的信息更改(地址信息,用户信息)

3.立即购买后续开发

4.购物车界面的实现(逻辑)

5.扫一扫,搜索,等等小功能点的完善

GIF展示部分功能

首页
详情

实现

主要介绍这次更新功能。

  • 登录TabBar拦截,以后成功后跳转

国美最新的登录思路是:在未登录的前提下,点击我的(个人中心)以及各项需登录后可查看的数据跳出登录界面,供用户点击登录。这里需特别说明:

① : 未登录在其他界面点击我的tabBarpresentViewController出登录界面
② : 输入账号密码登录后,登录界面dismissViewController后在要 ,切换到我的界面
③ :实现效果GIF

myCenter

④ :实现思路遵循<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


headZoom

② : 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


beautyShop

② : 美店这个界面

  • 我们首先隐藏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)。
Const
  • 展示下项目中所遇到的通知 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";
三、多整理一些Category(分类)和封装一些常用的小方法,在定义方法的时候建议加上下标如我在项目中会加上前缀dc_这样既可以避免和自带方法冲突也可以用区分。
四、之前有人私聊问过我为什么出现通知执行了两次的情况?因为通知没有remove。我们应该在delloc方法里remove掉 通知。如果你这么做通知还是执行两次那就检查下是否出现了内存循环导致其retainCount+1
五、建议延迟方式使用GCD,performSelector存在弊端如:参数对象的限定等。
六、为了提高效率我还是很建议来自定义代码块和初始化文件 - 自定义模板
tip:先总结这么多,后续有的话再补充~

项目地址 :RocketsChen/CDDStore

建议:强烈建议去GitHub下载一份源码。开源的过程中我学到了很多,项目写完就上传了可能会出现很多不足,欢迎issues我,喜欢的点个赞再走呗。

有空余时间会坚持持续更新,并且会把项目中所用到的进行封装和总结。欢迎指教~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,566评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,612评论 4 59
  • 二零一七年六月二十一日凌晨十二点五十二分,安静又凉爽,很困,但是不想睡。上午下过一场雨,但是下午还是很闷热,晚上...
    正在努力发o芽芽o阅读 540评论 4 2
  • 八一早上。下公车要转下一班,刚下车,一个头发灰白、精神矍铄的老人递过一张单页,我不明所以。但老人眼神...
    悠游碎笔阅读 212评论 0 2
  • 这两天古典老师谈的主题是如何战拖,别疑惑,就是如何战胜拖延症。 拖延症我相信每个人都有。但是是不是都要克服or治疗...
    lilycat阅读 244评论 0 0