iOS——ZARA仿写项目

iOS------ZARA仿写项目总结

文件结构

思路

搭建文件结构前,我们需要弄清楚MVC框架都需要哪些内容,我们从内容入手分析

  • 需要展示三个界面------首页,我的,分类,所以需要使用TabBar嵌套Navigation的方式实现

在SceneDelegate中创建:

objc 复制代码
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
    UIWindowScene *windowScene = (UIWindowScene *)scene;
    self.window = [[UIWindow alloc] initWithWindowScene:windowScene];
    
    ZAHomeViewController *home = [[ZAHomeViewController alloc] init];
    UINavigationController *homeNav = [[UINavigationController alloc] initWithRootViewController:home];
    homeNav.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"首页" image:[UIImage systemImageNamed:@"house"] tag:0];//控制器1
    
    ZACategoryViewController *cate = [[ZACategoryViewController alloc] init];
    UINavigationController *cateNav = [[UINavigationController alloc] initWithRootViewController:cate];
    cateNav.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"分类" image:[UIImage systemImageNamed:@"cart"] tag:0];//控制器2
    
    ZAProfileViewController *prof = [[ZAProfileViewController alloc] init];
    UINavigationController *profNav = [[UINavigationController alloc] initWithRootViewController:prof];
    profNav.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"我的" image:[UIImage systemImageNamed:@"person"] tag:0];//控制器3
    
    UITabBarController *bar = [[UITabBarController alloc] init];
    bar.viewControllers = @[homeNav, cateNav, profNav];//三个navigation塞进tabbar里面
    
    self.window.rootViewController = bar;
    [self.window makeKeyAndVisible];
}

以下是文件结构

MVC框架

复制代码
项目/
├── Controller/
│   ├── ZACategoryViewController.h
│   ├── ZACategoryViewController.m
│   ├── ZAHomeViewController.h
│   ├── ZAHomeViewController.m
│   ├── ZAProfileViewController.h
│   ├── ZAProfileViewController.m
│   ├── ZAUserDetailViewController.h
│   └── ZAUserDetailViewController.m
│
├── Model/
│   ├── ZAFuncModel.h
│   ├── ZAFuncModel.m
│   ├── ZAProfileModel.h
│   └── ZAProfileModel.m
│
└── View/
    ├── ZAFuncCell.h
    ├── ZAFuncCell.m
    ├── ZAProfileCell.h
    └── ZAProfileCell.m

我们先给出文件的结构,接着我会解释为什么这样设计:

从Model入手

  1. 我们知道Model要用于为需要复用的数据整理打包成一个数据结构,所以"我的"界面的tableView的信息就需要单独打包成Model,而且需要将个人信息与下面展示的界面分开,所以Model需要两个h/m文件
  2. 对应的View直接配套Model不多赘述
  3. 对于Controller首先需要三个h/m文件来完成首页,我的,分类的UI控制,其次需要点击头像进入cell界面,多接一个即可
  • 大体思路如此,下面我针对需要实现的重点内容进行讲解

重点需要实现的内容

无限轮播图

具体内容可以查看笔者这篇文章:iOS------无限轮播图学习

我们针对这里数据的初始化进行简单讲解

objc 复制代码
- (void)setupPicture {
    self.picture = @[@"005", @"001", @"002", @"003", @"004", @"005", @"001"];
    NSArray *strData = self.picture;
    UIImageView *prev = nil;
    for (NSInteger i = 0; i < strData.count; i++) {
        UIImageView *imageView = [[UIImageView alloc] init];
        imageView.image = [UIImage imageNamed:strData[i]];
        [self.scrollView addSubview:imageView];
        
        [imageView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.bottom.equalTo(self.scrollView);
            make.width.mas_equalTo(self.view.bounds.size.width);
            if (i == 0) {
                make.left.equalTo(self.scrollView);
            } else if (i == strData.count - 1) {
                make.left.equalTo(prev.mas_right);
                make.right.equalTo(self.scrollView);
            } else {
                make.left.equalTo(prev.mas_right);
            }
        }];
        prev = imageView;
    }
}
  • 首先创建数组,这里的数组内容是每个图片的名字,图片需要被放在Assets里面
  • 接着设置prev,这一步的目的是保证每张图片可以紧贴着上一张图片,当然也可以写死坐标,但这样不够灵活,也不够轻松
  • 可以看到,我们只需要单独约束第一章和最后一张的左右紧贴ScrollView,剩余图片只保证左边紧贴上一张图片(prev)的右边即可

UIPageControl与页面联动

objc 复制代码
- (void)setupPageControl {
    self.pageControl = [[UIPageControl alloc] init];
    self.pageControl.numberOfPages = self.picture.count - 2;
    self.pageControl.pageIndicatorTintColor = [UIColor whiteColor];
    self.pageControl.currentPageIndicatorTintColor = [UIColor grayColor];
    self.pageControl.currentPage = 0;
    [self.view addSubview:self.pageControl];
    
    [self.pageControl mas_makeConstraints:^(MASConstraintMaker *make) {
        make.bottom.equalTo(self.scrollView).offset(-8);
        make.centerX.equalTo(self.scrollView);
    }];
    [self.scrollView setContentOffset:CGPointMake(self.scrollView.bounds.size.width, 0) animated:NO];
}

上面是创建初始化pageControl,下面讲解同步更新pageControl

objc 复制代码
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    CGFloat currX = scrollView.contentOffset.x;
    CGFloat width = self.scrollView.bounds.size.width;
    
    if (currX <= 0) {
        [scrollView setContentOffset:CGPointMake(width * (self.picture.count - 2), 0) animated:NO];
    } else if (currX >= width * (self.picture.count - 1)) {
        [scrollView setContentOffset:CGPointMake(width, 0) animated:NO];
    }
    
    currX = scrollView.contentOffset.x;
    self.pageControl.currentPage = currX / width - 1;
}
  • 上方部分就是正常的无限轮播图的跳转逻辑
  • 注意看下面重新取了currX,原因是当中间的跳转逻辑生效之后,此时currX已经改变,为了同步更新pageControl,就要获得最新的currX

segmentControl与ScrollView联动

segmentControl与ScrollView的创建与初始化这里不多赘述,直接看联动逻辑

objc 复制代码
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    CGFloat currX = scrollView.contentOffset.x;
    CGFloat width = self.scrollView.bounds.size.width;
    currX += width / 2;
    NSInteger index = currX / width;
    self.seg.selectedSegmentIndex = index;
}

- (void)setupSeg {
    self.seg = [[UISegmentedControl alloc] initWithItems:@[@"女士", @"男士", @"香水"]];
    [self.seg addTarget:self action:@selector(segChange) forControlEvents:UIControlEventValueChanged];//绑定滑动方法
    self.seg.selectedSegmentIndex = 0;
    self.navigationItem.titleView = self.seg;
}

- (void)segChange {
    NSInteger index = self.seg.selectedSegmentIndex;
    CGFloat width = self.scrollView.bounds.size.width;
    [self.scrollView setContentOffset:CGPointMake(index * width, 0) animated:YES];//更新图片位置
}
  • 第一个方法currX += width / 2;是为了保证滑动到一半的时候更新segmentControl

多界面传值更新头像

这里我使用的是代理传值,也就是在ZAProfileCell.h里面声明协议,让Controller执行

objc 复制代码
- (void)exchangePicture:(NSString *)picture {
    ZAProfileModel *model = [[ZAProfileModel alloc] init];
    model.picture = picture;
    model.userName = @"dyyxs";
    model.subTitleName = @"秋雨梧桐叶落莳";
    [self.section replaceObjectAtIndex:0 withObject:model];
    NSIndexSet *set = [NSIndexSet indexSetWithIndex:0];
    [self.tableView reloadSections:set withRowAnimation:UITableViewRowAnimationFade];
}

//------------------------------------------分割线
#import <UIKit/UIKit.h>
#import "ZAProfileModel.h"

NS_ASSUME_NONNULL_BEGIN

@interface ZAProfileCell : UITableViewCell
@property (nonatomic, strong) ZAProfileModel *model;
- (void)configWithModel:(ZAProfileModel *)model;
@end

NS_ASSUME_NONNULL_END
相关推荐
科技侃谈12 分钟前
Windows和Mac日常使用推荐?联想小新 Air 15 给出大屏新答案
macos
世人万千丶17 分钟前
鸿蒙PC问题解决:窗口配置错误修复指南
android·学习·华为·开源·harmonyos·鸿蒙·鸿蒙系统
txh05071 小时前
串口数据调试-直观表示
嵌入式硬件·学习
Lucky_ldy1 小时前
51单片机的学习下(结合中科协的个人自用笔记)
笔记·学习·51单片机
PersistJiao1 小时前
针对 Intel Mac 的硬件限制提升faster-whisper字幕识别的方法
macos·whisper
OBiO20131 小时前
AAV在肠道研究中的应用:从血清型选择到炎症性肠病研究案例解析
学习
段一凡-华北理工大学1 小时前
工业领域的Hadoop架构学习~系列文章16:实时流处理架构 - 工业数据的实时动脉
大数据·数据仓库·hadoop·分布式·学习·架构·高炉炼铁
MartinYeung51 小时前
[论文学习]隐私保护联邦学习于入侵侦测系统之调查研究
学习
稷下元歌1 小时前
aifei学习前置基础:全套完整教程:Anaconda 安装→环境配置→YOLOv8+OpenCV 安装 + OpenCV 实操 + 标注→训练→导出→部署
opencv·学习·yolo
星恒随风1 小时前
Python 基础语法详解(3):顺序语句、条件语句和循环语句一篇讲清楚
开发语言·笔记·python·学习