Administrator
发布于 2026-02-16 / 1 阅读
0
0

SwiftUI大型项目简介(主要电商举例)

下面我给你一份可以直接拿去当“项目手册/规范”用的内容:分层模板、状态隔离、性能安全写法、反模式清单,以及电商(超详细)/ IM / 后台管理的实践总结。最后我会回答你“后台管理为什么通常是 Web、SwiftUI 能不能做 Web”。

  1. 大型 SwiftUI 项目分层模板(可落地)

1.1 目标 • UI 纯声明式:View = f(State) • 业务收敛:不让 body 承担业务逻辑 • 副作用统一:网络/缓存/埋点/权限/AB 统一入口 • 导航可控:Router 统一管理 push/pop/deeplink • 可测试:Interactor/UseCase 可替换为 mock

1.2 目录结构(模块化)

适合电商/IM 这种会爆炸的业务:

App/ AIChatsApp.swift AppEnvironment.swift // DI & 全局配置(env, feature flags) AppRouter.swift // 顶层路由(tab、deeplink) AppAppearance.swift // 主题/字体/颜色

Core/ // 可复用基础设施(横跨业务) Networking/ NetworkClient.swift Request.swift Response.swift RetryPolicy.swift CachePolicy.swift Persistence/ CacheStore.swift // 文件/SwiftData/Keychain 统一接口 KeyValueStore.swift Observability/ Logger.swift Analytics.swift CrashReporter.swift DesignSystem/ DSButton.swift DSTextField.swift DSColors.swift DSTypography.swift Utils/ TaskDebounce.swift Throttle.swift Atomic.swift

Features/ // 业务模块(强边界) Home/ HomeView.swift HomePresenter.swift // @Observable / @MainActor HomeInteractor.swift HomeModels.swift HomeRouter.swift HomeAssembly.swift // 装配:注入依赖 Product/ Cart/ Checkout/ Orders/ Profile/ Chat/ Admin/ // 若有后台(iPad/内部工具)

你之前的“临时 VIPER 架构”非常接近这个方向:View/Presenter/Interactor/Router/Entity/DI 都有了,只需要把 Core 抽出来并把 Feature 的边界更强。

  1. 状态隔离策略(大型项目的生死线)

SwiftUI 大型项目最容易死在:状态乱。这套策略能避免 80% 的坑。

2.1 三层状态模型

A. View State(瞬时 UI)

只用于 UI 状态,不出 View: • 输入框内容、是否展开、动画状态、局部 loading

用:@State

B. Feature State(页面/模块状态)

一个页面或一个 Feature 的状态集合: • 列表数据、分页状态、错误、筛选条件、是否可下单

用:@Observable 的 Presenter(或 StateObject VM)

C. App State(全局共享)

跨模块共享、且生命周期长: • 登录态、token、地区、AB 实验、全局购物车数量、主题

用:AppEnvironment / Store(可用 @Observable + 注入)

原则:能不全局就不全局。

2.2 单向数据流(推荐)

你不一定要上 Redux,但你要做到“方向一致”:

View -> Action -> Presenter -> Interactor(副作用) -> State -> View • View 不直接请求网络 • Presenter 不直接操作数据库/网络 • Interactor 负责副作用(网络/缓存/埋点/权限)

2.3 状态“收敛点”

大型项目常见灾难:一个状态被 5 个地方改。

做法: • 每个 Feature 只有一个“写入口”(Presenter 的方法) • View 只能触发 Action(按钮点击、刷新、滚动触底)

  1. 性能安全写法(SwiftUI 大项目必须会)

3.1 列表与大数据 • 永远优先:ScrollView + LazyVStack 或 List • 模型必须 Identifiable 且 id 稳定(不要用 index) • 避免在 body 做 map/filter/sort(放到 Presenter 预处理) • 图片:必须异步 + 缓存(你已经在做 ImageLoader,很好) • 尽量减少 GeometryReader 在列表里滥用(用一次就够)

3.2 视图重绘控制 • 把复杂 cell 拆小:RowView 内部只依赖必要 state • 对稳定子树用 .equatable()(谨慎) • 避免把“大对象”整个作为参数传给很多子 View(只传必要字段) • 避免在 body 创建 DateFormatter/NumberFormatter(放静态/缓存)

3.3 并发与任务 • .task(id:) 让任务可控,避免重复请求 • 输入框搜索用 debounce(避免每次输入就请求) • 分页触底必须防抖/锁(避免多次触发)

  1. 常见反模式清单(踩一次就会痛)
    1. 业务写进 body • if token == nil { login() } 这类逻辑放 body 会反复触发
    2. EnvironmentObject 滥用 • 全项目到处注入一个大对象,导致任何变化全局重绘
    3. 在列表里写 GeometryReader + PreferenceKey 满天飞 • 会引发性能和布局抖动(能不用就不用)
    4. onAppear 触发网络请求但列表 cell 频繁出现 • cell onAppear 会被反复调用,导致重复请求
    5. 用 index 当 id • 列表插入删除时动画/状态错乱
    6. 把 UIKit “算屏幕宽度” 思维带进 SwiftUI • iOS 26 之后更明显(你已经遇到 UIScreen.main deprecate)

  1. SwiftUI 实战经验总结(电商 / IM / 后台管理)

下面是你要的“非常非常详细”,尤其电商。我会按业务模块把关键设计点、状态、坑、性能点都讲清楚。

5.1 电商(非常详细)

电商项目的复杂点不在 UI,而在: • 状态多且联动强:购物车、库存、价格、优惠、地址、运费、支付、风控、售后 • 接口多且有一致性要求:同一商品在不同页面价格必须一致 • 列表巨大:首页、搜索、分类、推荐、订单列表、售后列表 • 强离线/缓存需求:弱网、秒开、回退一致性

5.1.1 首页(Home)

典型结构:banner + 分类 + 活动位 + 推荐流 + 楼层组件(你 diy 动态组件就是这个)

关键策略 1. 渲染模型统一

•	HomeComponent 协议 / enum + associated model
•	Presenter 负责把后端 JSON “变成可渲染组件数组”
•	View 只 ForEach components

2.	组件高度与性能

•	“广告位/活动位”用固定比例
•	“商品流”用 LazyVStack
•	“混合组件”慎用嵌套 ScrollView(会手势冲突)

3.	缓存策略

•	首屏必须本地缓存:上次组件配置 + 上次商品流前 N 条
•	进入首页:先展示缓存,再后台刷新 diff(你之前说的“本地先比对再保存”非常适合首页)

4.	埋点

•	首页必须有曝光埋点:组件曝光、商品曝光(需要节流 + 可见区域判断)
•	点击埋点:banner、类目、商品卡、活动位

坑 • 首页组件化最容易“状态分散”:每个组件自己请求网络导致整体不可控 ✅ 做法:统一在 HomeInteractor 请求,组件只消费数据

5.1.2 商品列表(PLP:category/search/reco list)

这里是性能核心。

关键策略 1. 列表 item 模型必须轻量(只放展示字段) 2. 图片加载必须缓存 + 占位 3. 筛选/排序改变时:Presenter 生成 query state,然后触发刷新 4. 分页:必须有 isLoadingNextPage 锁 + hasMore 标记 5. “同一商品多处显示一致性”:用 ProductSnapshot(轻量快照)+ ProductStore(缓存最新价格/库存)

坑 • 搜索联想:输入每次请求会炸 ✅ debounce(300~500ms)+ cancel previous task

5.1.3 商品详情页(PDP)

最复杂:价格、库存、SKU、优惠、运费、评价、推荐、客服、收藏

推荐状态划分 • ProductDetailState:详情、sku、库存、价格、优惠、加载状态、错误 • SelectedSKUState:用户选择的规格路径 • CTAState:按钮状态(可买/缺货/限购/风控/预售)

关键策略 1. PDP 首屏快:先展示缓存快照(图、标题、基础价)再补全接口 2. SKU 选择需要“可用性矩阵”(禁用不可选项) 3. 加购/立即买:必须防抖 + loading + 幂等(你之前支付按钮慢、多次点击就是同类问题)

坑 • PDP 的“一个动作触发多处更新”:选 SKU -> 价/库存/按钮状态全变 ✅ Presenter 做一个 reduce(action:),集中更新 state

5.1.4 购物车(Cart)

购物车本质是一个“强一致性状态机”。

核心问题 • 数量变化触发:库存校验、价格变化、优惠变化、运费变化 • 同步:本地修改 vs 服务端回写 • 批量操作:全选、删、移入收藏、凑单

推荐策略:分两层 1. CartLocalDraft(本地草稿状态,响应 UI 快) 2. CartServerSnapshot(服务端确认状态)

流程: • 用户点 +/−:先改 draft(UI 秒响应) • 后台触发 syncCart(可合并请求、节流) • 服务端返回 snapshot:对齐 draft(必要时提示价格变化)

坑 • 直接每点一次就请求,会卡死 ✅ throttle + batch sync(比如 800ms 内合并)

5.1.5 结算(Checkout)

结算是电商“最容易出 bug 的地方”。

关键点: • 地址、发票、优惠券、积分、运费、支付方式都可能改变应付金额 • 最终支付前必须“锁价/锁库存”

推荐状态机 • editing:可改地址/券/配送 • confirming:点击提交订单,锁定请求进行中 • locked:拿到订单号/支付信息,只允许支付或取消

坑 • 用户在锁价后返回修改导致状态错乱 ✅ Router + state machine 防止非法操作

5.1.6 订单与售后

订单状态多:待支付/待发货/运输中/已完成/已取消/售后中…

关键策略 • 订单列表展示用轻量模型 • 订单详情用重模型 • 状态映射统一:后端状态码 -> 前端 OrderStatus enum(统一文案/按钮)

售后(退款/退货): • 多步表单:原因、凭证、金额、物流 • 必须保存草稿(避免用户退出丢失)

5.1.7 电商里 SwiftUI 的“最佳工程实践” • 强模块化:Home/Product/Cart/Checkout/Orders/Profile 互不直接依赖 • 统一 Design System:按钮、输入框、价格、标签(减少重复) • 统一格式化:价格、货币、时间 • 统一错误处理:弹窗、toast、空状态、重试 • 统一埋点:曝光/点击/转化漏斗(尤其首页与 PDP)

你现在的工程方向(网络层封装、缓存策略、模块化、Router)非常适合电商。

5.2 IM(聊天系统)

IM 的核心难点: • 列表性能(大量消息) • 滚动定位(新消息插入、历史加载) • 键盘处理 • 消息类型(文本/图片/语音/卡片/引用/撤回)

SwiftUI 做 IM 的现实策略: • 80% SwiftUI(气泡、输入栏、顶部信息) • 20% UIKit(当你需要极致性能的消息列表,很多团队会用 UICollectionView 做 message list,然后 SwiftUI 嵌进去)

但现在 iOS 26+ SwiftUI 自己做聊天也可用,关键是: • ScrollViewReader 管滚动 • 插入消息用 withAnimation 控制 • 历史加载用“顶部触发 + 锁” • 图片/富文本要缓存并异步

5.3 后台管理系统(为什么你觉得应该是 Web)

你惯性非常正确:大多数后台是 Web,原因是工程与业务效率: • 运营/客服/财务用电脑办公:浏览器天然合适 • 更新发布快:前端改动不用上架 • 权限系统/表格/批量操作:Web 生态成熟(React/Ant Design) • 跨平台:Windows/Mac 都能用

SwiftUI 能不能实现到 Web 上?

不能直接把 SwiftUI 编译成“Web 页面”跑在浏览器里。

SwiftUI 的渲染目标是 Apple 平台的 UI 系统(iOS/macOS/visionOS),不是 DOM。

你可以有几种“接近 Web”的路线,但都不是“SwiftUI 直接上 Web”: 1. SwiftUI 做 macOS/iPad 内部后台工具 • 很多公司会做“内部管理 App”(iPad/macOS) • 优点:权限、扫码、拍照、打印、离线都很强 • 缺点:部署没 Web 快 2. Web 后台 + iOS SwiftUI 作为运营端辅助 • 主后台 Web • iOS App 做“移动运营工具”(审核、处理工单、上架、看数据) 3. Swift/Wasm + Web UI(不是 SwiftUI) • Swift 可以跑 WebAssembly,但 UI 通常还是 Web 技术栈(HTML/CSS/JS 或 Swift 专用 Web 框架) • 这条路目前工程成熟度不如 React/Vue 4. SwiftUI 包 WebView(这只是加载 Web,不是 SwiftUI 变 Web) • 在 SwiftUI 里嵌后台网页,用作壳

结论:后台管理绝大多数仍然 Web 最优;SwiftUI 更适合做“内部 App 工具”和“移动运营端”。

  1. 你下一步怎么用这份内容(给你一个“落地路线”)

你在做电商/IM 的话,我建议你的落地顺序: 1. 先把 Features 按模块切清(Home/Product/Cart/Checkout/Orders/Chat) 2. Core 抽出来(Networking / Cache / Logger / DS) 3. 每个模块统一用:Presenter + Interactor + Router 4. 购物车/结算用状态机(避免后期爆炸) 5. 首页/列表做缓存与性能规范(秒开 + 防抖 + 分页锁)

如果你愿意,我可以进一步给你两份“超落地”的东西(不需要你再补充信息): 1. 电商全模块 State/Action/Interactor 接口草图(像规范文档一样) 2. 一个可以直接复用的 SwiftUI “电商架构模板仓库结构”(每个文件应该放哪、叫什么、职责是什么)

你更想先看哪一个?(我不需要你答也能直接先给你“电商模块草图”版。)


评论