概览
功能完备的 SwiftUI iOS 起始模板,内置 Supabase、RevenueCat、推送通知与数据分析。
Swift (iOS) 模板是一套功能完备的 SwiftUI 起始项目,同时适配 iPhone 与 iPad。 它已经把身份认证、Supabase 后端、基于 RevenueCat 的跨平台订阅、推送通知、深度链接、 数据分析、崩溃上报,以及完整的启动闸门栈(引导页、法律同意、生物识别锁、强制更新) 全部串联好——让你专注于产品本身,而不是底层管道。
上述核心服务均已端到端接好。部分界面是可运行的 Example(示例) 功能或一个 Removable demo(可移除演示),需要你在上线前替换掉。下方的 功能状态表会明确说明哪些已集成、哪些需要你自行替换。
最低 iOS 版本:17.0。目标设备:iPhone + iPad。使用 Xcode 16+ 构建。
优雅降级
所有密钥都是可选的。缺失某个密钥不会导致崩溃——对应的控制器会将
isConfigured 置为 false 并空转,因此项目在零配置下也能构建并启动。你可以按需
逐个接入各项服务。这是本模板的核心行为;每个服务页面都会说明其密钥缺失时的具体表现。
参见配置。
技术栈
| 层次 | 选型 |
|---|---|
| 界面 | SwiftUI(iOS 17+) |
| 架构 | MVVM(@Observable 视图模型)+ Repository 模式 |
| 依赖注入 | 通过 @Environment 注入的 AppEnvironment 容器(不使用 Swinject/Factory) |
| 导航 | NavigationStack + Hashable 路由枚举;TabView 主壳 |
| 后端 | supabase-swift(Auth、PostgREST、Storage) |
| 并发 | Swift 并发(async/await、AsyncStream),默认 MainActor 隔离 |
| 会话存储 | iOS 钥匙串(通过 supabase-swift 的 KeychainLocalStorage) |
| 应用状态 | UserDefaults(AppPreferences 封装) |
| 图片加载 | Kingfisher(配合轻量的 RemoteImage 封装) |
| 订阅 | RevenueCat(purchases-ios) |
| 推送 | 通过 UNUserNotificationCenter + UIApplicationDelegateAdaptor 接入 APNs |
| 数据分析 | PostHog(posthog-ios) |
| 崩溃上报 | Sentry(sentry-cocoa) |
| 生物识别 | LocalAuthentication(LAContext) |
| 应用内评分 | StoreKit requestReview(in:) |
| 深度链接 | 通用链接 + 自定义 soar:// scheme |
| 国际化 | Localizable.xcstrings 字符串目录(英文 + 简体中文) |
功能状态
本文档统一使用以下标签:
- Integrated(已集成) — 完全接好;配置对应密钥或服务后即生效。
- Example(示例) — 可运行的演示功能,供你替换为自己的实现。
- Removable demo(可移除演示) — Showcase 标签页;可一步删除且不影响核心代码。
- Device-only(仅限真机) — 需要真机以及付费 Apple 开发者团队。
| 功能 | 状态 | 说明 |
|---|---|---|
| 身份认证 | Integrated | 邮箱/密码、注册 + 邮箱 OTP、找回/重置、修改邮箱/密码、登出其他会话、注销账户 |
| Google 登录 | Integrated | 原生 SDK 的 ID token → Supabase;需要 GOOGLE_IOS_CLIENT_ID(未配置时按钮变暗) |
| Apple 登录 | Integrated | ASAuthorizationController → Supabase signInWithIdToken;需要 Sign in with Apple 能力 |
| 订阅 | Integrated | RevenueCat 付费墙(月/年/永久);权益从共享的 Supabase subscriptions 表读取 |
| 推送通知 | Device-only | 仅在配有付费团队的真机上才能完成 APNs 注册 |
| 深度链接 | Integrated | soar:// scheme + 通用链接,可路由到所有主要目的地 |
| 数据分析 | Integrated | PostHog 类型化事件、经同意后启动、随登录/登出 identify/reset |
| 崩溃上报 | Integrated | Sentry,带用户标记、ErrorBoundary、用户反馈入口 |
| 启动闸门 | Integrated | 生物识别锁、强制/软性更新、引导页、法律同意 |
| 应用评分 | Integrated | StoreKit 智能触发(操作次数 + 版本 + 90 天冷却) |
| 国际化 | Integrated | 英文 + 简体中文,运行时切换语言 |
| 主题 | Integrated | 浅色 / 深色 / 跟随系统,持久化保存 |
| 离线横幅 | Integrated | 全局挂载的 NetworkObserver(NWPathMonitor) |
| Toast / 触感 | Integrated | 顶部 Toast 浮层,配合成功/失败触感反馈 |
| 待办 | Example | 完整 CRUD 参考功能——照它的形态实现你自己的数据 |
| 上传示例 | Example | PhotosPicker → Supabase Storage,逐任务进度 |
| 个人资料 | Example | 头像、个人信息、账户与安全页面 |
| 推荐好友 | Example | ShareLink + 推荐链接 |
| Showcase | Removable demo | 全能力目录;可一步删除 |
应用界面地图
应用由外到内分为三层:
- 闸门栈 —
RootView用一系列闸门包裹整个应用,按顺序求值:ErrorBoundary → Biometric → Update → Onboarding → Consent → Auth。每道闸门在 满足前都会阻断其下各层。参见启动闸门。 - 认证栈 — 无会话时,一个小型
NavigationStack驱动登录 / 注册 / 验证 / 找回密码等页面。参见身份认证。 - 主壳 — 登录后,
MainShellView挂载一个含四个标签页(Home、 Component、Showcase、Me)与侧边抽屉的TabView。每个标签页各持有自己的NavigationStack(path:),因此切换标签时返回栈得以保留。
跨平台权益
订阅是账户绑定的,而非设备绑定。一次购买会经由 RevenueCat webhook 写入共享的
Supabase subscriptions 只读模型,应用读取的是这张表——而非 RevenueCat SDK 的
CustomerInfo——作为唯一可信来源。该只读模型与桌面端模板共享,因此在一个平台购买的
权益也会在另一平台生效。参见订阅。
从这里开始
按以下路径从克隆走到可上线的应用:
