高仿国美商城

作者: RocketsChen | 来源:发表于2017-12-14 22:04 被阅读11104次

前言

开源高仿商城已经半年了,这半年基本上有时间的就在持续更新,收获了很多。从一开始随意的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我,喜欢的点个赞再走呗。

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

相关文章

网友评论

  • 6ed822f9aedb:这是xcode 10版本的,楼主,有空看看。
    Showing All Messages
    :-1: Multiple commands produce '/Users/pangxianfei/Library/Developer/Xcode/DerivedData/CDDStoreDemo-hcnraenslcsdxocnxekszhgguvou/Build/Products/Debug-iphonesimulator/CDDStoreDemo.app':
    1) Target 'CDDStoreDemo' has create directory command with output '/Users/pangxianfei/Library/Developer/Xcode/DerivedData/CDDStoreDemo-hcnraenslcsdxocnxekszhgguvou/Build/Products/Debug-iphonesimulator/CDDStoreDemo.app'
    2) That command depends on command in Target 'CDDStoreDemo': script phase “[CP] Copy Pods Resources”
    黑夜飞鹰:更新下pod就可以了
    6ed822f9aedb:@RocketsChen 了解。
    RocketsChen:@pangfei 目前还没有更新
  • 不曾停息:[_topAdImageView sd_setImageWithURL:[NSURL URLWithString:HomeBottomViewGIFImage]];你用SD怎样加载gif图的
    ,请教一下
  • PGOne爱吃饺子:你好,看了你的商城项目,在个人中心页面cell里面为什么会有一条线啊,我看了你的源码怎么没有找到你设置的地方,好奇怪。能不能说一下
  • 翻滚的炒勺2013:有测试账号吗
  • Jacky__燊:您好、请教您一下demo里有个小问题,详情页里面上拉显示了webview,下拉返回商品信息页面,当再次上拉后发现header的位置乡下偏移了,多次上拉下拉后发现这个偏移量越来也大,这个请问怎么解决~~ 求大神指教。
    Jacky__燊:@RocketsChen 大神 截图已发至您的邮箱。谢谢指点。
    Jacky__燊:@RocketsChen 大神您好、1844886263 这是我QQ
    RocketsChen:@Jacky__燊 方便的话给我看下具体截图
  • 4ab2317387a7:太好了,刚开始学习。希望持续更新~~!!赞一个
  • GrowthGou:很厉害,可以的
  • 我的发:很不错的项目,值得学习.敢问博主多少年开发经验了?
  • bd897158e6ae:期待博主持续更新
  • iOS_渔翁:你好, 有个问题想请教一下, 我看你的返回用的是那个FD, 和scrollView滑动冲突解决的非常好, 我想问下那个手势返回 和 tableViewCell左滑删除冲突怎么解决, 比如购物车作为二级界面, 左滑删除和右滑返回会冲突, 左滑删除一直触发不了, 希望大神指点, 或是在这个项目中解决, 万分感谢,一直在追你这个项目, 感谢.学习中...:stuck_out_tongue_winking_eye:
    bd897158e6ae:挺好的,star了
    RocketsChen:@iOS_渔翁 这种需求我见得比较少,一般集成子控制器的切换上可以在Cell上添加点击事件或按击力度的识别或者Nav的右上角来统一进行编辑删除等操作管理。
    RocketsChen:@iOS_渔翁 首先谢谢,你的这个问题思路点可以从拦截UIScrollView的手势方法出发去考虑,通过触摸点来进行一层过滤,或者可以另辟蹊径通过判断当前手指滑动的点击位置占于屏幕的百分比作为是否开始cell编辑状态或者滑动UIScrollView到下一个子界面。
  • 菜鸟晋升路:现在基本只完成了UI层面,逻辑基本没完成 加油
  • iOS_渔翁:这两天不太忙, 正在看你的这个demo,学习一下你的设计思路, 我的项目中也使用到了FD全局手势返回, 但是购物车作为二级界面的时候, 购物车cell的左滑删除,和右滑返回怎么区分? 总是手势冲突, 禁掉手势返回可以,但是感觉体验不太好,不禁掉,左滑删除cell老是触发不了, 参考了小米家的米家有品APP,感觉人家处理的很好,求解答
  • zl520k:iTunes已经不能下载ipa包了,请问从哪儿下载ipa包?
    zl520k:@RocketsChen 谢谢!
    RocketsChen:@zl520k 旧版本iTunes,或者iTools苹果助手
  • Kris_A:看你的代码,能让我学到很多思路和代码规范,感谢作者:pray::pray:
    Kris_A:@RocketsChen 期待您的更新:smiley::smiley:
    RocketsChen:@抨击者 谢谢
  • 哈哈大笑呼呼呼呼:不错越来越完善:smile:
    RocketsChen:@SunMengK 有时间,还会持续完善
  • 北纬357:当时看这个项目的时候还没有完善 现在越来越完善了
    哈哈大笑呼呼呼呼:不错,希望越来越完善:+1:
    RocketsChen:@控心KX 谢谢:grin:
  • f99be83ff259:一直不太会用collectionView特地过来学习的
    RocketsChen:@juicex :grin:
  • Jacky__燊:期待大神您的购物车更新 0.0

本文标题:高仿国美商城

本文链接:https://www.haomeiwen.com/subject/eojkwxtx.html