程序主入口
了解 EasyAppSwiftUI 的程序主入口做了哪些事情
程序主入口 - ContentView
ContentView 是 EasyAppSwiftUI 应用程序的主入口点,负责初始化和配置应用程序的核心组件、状态管理器和环境对象。
核心架构
状态管理器初始化
ContentView 初始化了多个关键的状态管理器:
struct ContentView: View {
/// App state - 应用程序全局状态
@StateObject private var appState = AppState()
/// Auth Manager - 认证管理器
@StateObject private var authManager = AuthManager.shared
/// RevenueCat - 内购管理(RevenueCat)
@StateObject private var revenueCatManager = RevenueCatManager.shared
/// StoreKit2 - 内购管理(StoreKit2)
@StateObject private var storeKit2Manager = StoreKit2Manager.shared
}主要功能模块
-
应用状态管理 (
AppState)- 管理应用程序的全局状态
- 协调各个模块之间的数据共享
-
用户认证 (
AuthManager)- 处理用户登录、注册和身份验证
- 管理用户会话状态
-
内购系统
RevenueCatManager: 基于 RevenueCat 的内购管理StoreKit2Manager: 基于 StoreKit2 的内购管理- 支持双重内购方案,提供更好的兼容性
视图结构
主视图配置
var body: some View {
MainView()
.showAuthView() // 显示认证视图
.showPaywallSheetWhenCalled() // 显示付费墙
.environmentObject(appState) // 注入应用状态
.environmentObject(authManager) // 注入认证管理器
.environment(
\.whatsNew,
.init(
versionStore: UserDefaultsWhatsNewVersionStore(),
whatsNewCollection: self
)
) // 配置新功能介绍
.environmentObject(revenueCatManager) // 注入 RevenueCat 管理器
.environmentObject(storeKit2Manager) // 注入 StoreKit2 管理器
}视图修饰器说明
.showAuthView(): 自动显示认证界面,当用户未登录时触发.showPaywallSheetWhenCalled(): 响应付费墙调用,显示订阅界面- 环境对象注入: 通过
environmentObject将管理器注入到整个视图层次结构中
核心修饰器详解
showAuthView() - 认证视图管理器
showAuthView() 是一个关键的视图修饰器,负责管理整个应用的用户认证流程。
实现原理
extension View {
/// Show Auth View
/// This function is used to show the auth view.
/// - Returns: A view with a auth view.
func showAuthView() -> some View {
modifier(AuthViewModifier())
}
}主要功能
-
自动认证检测
- 监听用户登录状态变化
- 当用户未认证时自动弹出登录界面
- 认证成功后自动隐藏登录界面
-
无缝用户体验
- 在后台静默检查认证状态
- 保持用户操作的连续性
- 避免不必要的界面跳转
-
状态管理集成
- 与
AuthManager深度集成 - 响应认证状态的实时变化
- 支持自动刷新和重新认证
- 与
showPaywallSheetWhenCalled() - 全局付费墙监听器
showPaywallSheetWhenCalled() 是一个全局付费墙监听器,它通过通知系统与 AuthManager.actionGoPaywall() 配合工作。
实现原理
extension View {
/// Show Paywall Sheet When Called
/// This function is used to show the paywall sheet when called.
/// - Returns: A view with a paywall sheet.
func showPaywallSheetWhenCalled() -> some View {
self.modifier(ShowPaywallSheetWhenCalledModifier())
}
}工作机制
-
通知监听
- 监听
Constants.Notifications.showPaywall通知 - 在 ContentView 根级别设置,实现全局覆盖
- 通过
NotificationCenter响应付费墙调用
- 监听
-
与 AuthManager 集成
- 配合
AuthManager.actionGoPaywall()方法使用 - 当用户无订阅时,actionGoPaywall 发送通知
- 监听器接收通知后展示相应的付费墙
- 配合
AuthManager.actionGoPaywall() 方法
extension AuthManager {
public func actionGoPaywall(
subscriptionType: SubscriptionType = .revenueCat,
sheetOrFullScreenCover: SheetOrFullScreenCover = .sheet,
_ closure: () -> Void
) {
if subscriptionActive {
closure() // 用户已订阅,执行业务逻辑
} else {
// 发送通知显示付费墙
let notificationData = PaywallNotificationData(
subscriptionType: subscriptionType,
sheetOrFullScreenCover: sheetOrFullScreenCover
)
NotificationCenter.default.post(
name: Constants.Notifications.showPaywall,
object: nil,
userInfo: notificationData.userInfo
)
}
}
}使用方式
在应用中的任何位置都可以通过以下方式调用付费墙:
// 在任意视图中使用
Button("使用高级功能") {
authManager.actionGoPaywall(
subscriptionType: .revenueCat,
sheetOrFullScreenCover: .sheet
) {
// 用户已订阅时执行的业务逻辑
print("执行高级功能")
performPremiumAction()
}
}架构优势
- 全局管理: 在根视图统一处理所有付费墙展示
- 解耦设计: 业务逻辑与 UI 展示完全分离
- 灵活调用: 可以在应用的任何位置触发付费墙
新功能引导 (WhatsNewKit)
ContentView 实现了 WhatsNewCollectionProvider 协议,提供应用更新时的新功能介绍:
协议实现
extension ContentView: WhatsNewCollectionProvider {
var whatsNewCollection: WhatsNewCollection {
// 当前版本的新功能介绍
WhatsNew(
version: .current(),
title: "News App2",
features: [
.init(
image: .init(
systemName: "apps.iphone",
foregroundColor: .black
),
title: "Welcome to the News App",
subtitle: "This is a news app that allows you to read news articles"
)
],
primaryAction: .init(
title: "OK",
hapticFeedback: .notification(.success)
),
secondaryAction: WhatsNew.SecondaryAction(
title: "Learn more",
foregroundColor: .accentColor,
hapticFeedback: .selection,
action: .openURL(
.init(string: "https://github.com/SvenTiigi/WhatsNewKit")
)
)
)
// 历史版本的新功能介绍
WhatsNew(
version: "1.0.0",
title: "Welcome to the News App",
features: [
.init(
image: .init(
systemName: "newspaper",
foregroundColor: .black
),
title: "Welcome to the News App",
subtitle: "This is a news app that allows you to read news articles"
)
],
primaryAction: .init(
title: "OK",
hapticFeedback: .notification(.success)
)
)
}
}新功能引导特性
- 版本管理: 使用
UserDefaultsWhatsNewVersionStore存储已显示的版本 - 触觉反馈: 集成了触觉反馈系统,提升用户体验
- 多版本支持: 可以定义多个版本的新功能介绍
- 自定义操作: 支持主要操作和次要操作按钮
关键特性
1. 依赖注入架构
通过 @StateObject 和 environmentObject 实现了清晰的依赖注入模式,确保:
- 单一数据源
- 状态共享
- 模块解耦
2. 多种内购方式支持
同时集成 RevenueCat 和 StoreKit2,提供:
- 更好的平台兼容性
- 灵活的商业化策略
- 备用方案支持
3. 用户体验优化
- 自动认证流程
- 平滑的付费墙体验
- 新功能引导系统
- 触觉反馈集成
使用建议
1. 认证流程最佳实践
// 在需要认证保护的视图中使用
NavigationStack {
TabView {
// 主要功能页面
HomeView()
.tabItem {
Label("首页", systemImage: "house")
}
ProfileView()
.tabItem {
Label("个人", systemImage: "person")
}
}
}
.showAuthView() // 在最外层添加认证保护2. 付费墙集成策略
// 使用 actionGoPaywall 进行付费保护
VStack {
Text("高级功能")
Button("使用 AI 功能") {
authManager.actionGoPaywall(
subscriptionType: .revenueCat,
sheetOrFullScreenCover: .sheet
) {
// 用户已订阅时执行的 AI 功能逻辑
performAIFeature()
}
}
Button("使用专业工具") {
authManager.actionGoPaywall(
subscriptionType: .storeKit2,
sheetOrFullScreenCover: .fullScreenCover
) {
// 用户已订阅时执行的专业工具逻辑
openProfessionalTools()
}
}
}
// 全局付费墙监听 - 在根视图添加
ContentView()
.showPaywallSheetWhenCalled()3. 两种付费保护机制
EasyAppSwiftUI 提供了两种不同的付费保护机制:
actionGoPaywall (推荐使用)
// 通过 AuthManager 的 actionGoPaywall 方法
@EnvironmentObject private var authManager: AuthManager
Button("高级功能") {
authManager.actionGoPaywall(
subscriptionType: .revenueCat, // 或 .storeKit2
sheetOrFullScreenCover: .sheet // 或 .fullScreenCover
) {
// 已订阅用户的业务逻辑
executeAdvancedFeature()
}
}requirePremium (视图级保护)
// 直接在视图上应用付费保护修饰器
AdvancedFeatureView()
.requirePremium(
subscriptionType: .revenueCat,
sheetOrFullScreenCover: .sheet,
onCancelPaywall: {
print("用户取消了付费")
},
onPaySuccess: {
print("用户订阅成功")
}
)两种方式的区别
- actionGoPaywall: 基于通知系统,全局统一管理,与
showPaywallSheetWhenCalled()配合使用 - requirePremium: 视图级别的保护,直接在视图上应用,独立工作
4. 开发和调试建议
基础配置
- 自定义新功能介绍: 修改
whatsNewCollection中的内容以适配你的应用 - 环境配置: 根据需要添加或移除环境对象
- 状态管理: 利用注入的管理器进行状态操作
- 模块化开发: 在子视图中通过
@EnvironmentObject访问这些管理器
认证与付费测试
- 测试认证流程: 在开发过程中测试登录、登出和会话过期场景
- actionGoPaywall 测试: 验证不同订阅状态下的逻辑分支
- 通知系统验证: 确保
showPaywallSheetWhenCalled正确响应通知 - 付费墙展示测试: 验证 sheet 和 fullScreenCover 两种展示方式
调试技巧
// 在 actionGoPaywall 中添加调试信息
authManager.actionGoPaywall {
print("✅ 用户已订阅,执行高级功能")
// 业务逻辑
}
// 监听付费墙通知 (调试用)
NotificationCenter.default.addObserver(
forName: Constants.Notifications.showPaywall,
object: nil,
queue: .main
) { notification in
print("🔔 收到付费墙显示通知: \(notification.userInfo ?? [:])")
}架构优势总结
认证与付费的统一管理
showAuthView() 和 showPaywallSheetWhenCalled() 这两个修饰器在 ContentView 中的应用体现了以下架构优势:
-
集中式控制
showAuthView(): 在应用入口统一管理用户认证状态showPaywallSheetWhenCalled(): 通过通知系统全局监听付费墙展示请求- 简化了各个子模块的实现复杂度,提供一致的用户体验
-
松耦合设计
- 认证保护通过修饰器自动应用,子视图无需关心具体实现
- 付费墙通过
AuthManager.actionGoPaywall()与通知系统解耦 - 业务逻辑与 UI 展示完全分离,便于测试和维护
-
灵活的付费保护策略
- 全局通知方式:
actionGoPaywall()+showPaywallSheetWhenCalled() - 视图级保护:
requirePremium()修饰器 - 支持 RevenueCat 和 StoreKit2 双重方案
- 可根据场景选择不同的展示方式(sheet/fullScreenCover)
- 全局通知方式:
开发效率提升
- 快速集成: 只需在根视图添加两个修饰器即可获得完整的认证和付费基础设施
- 统一管理: 所有认证和付费相关的状态都通过管理器集中处理
- 代码复用: 修饰器和管理器可以在不同项目中复用
- 调试友好: 通过通知系统可以轻松跟踪付费墙的触发和展示
ContentView 作为应用程序的核心入口,通过 showAuthView() 提供认证保护,通过 showPaywallSheetWhenCalled() 建立全局付费墙监听机制,配合 AuthManager.actionGoPaywall() 实现了完整的用户认证和商业化基础设施,为整个应用的功能模块奠定了坚实的架构基础。
Last updated on