EasyApp

程序主入口

了解 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
}

主要功能模块

  1. 应用状态管理 (AppState)

    • 管理应用程序的全局状态
    • 协调各个模块之间的数据共享
  2. 用户认证 (AuthManager)

    • 处理用户登录、注册和身份验证
    • 管理用户会话状态
  3. 内购系统

    • 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())
    }
}

主要功能

  1. 自动认证检测

    • 监听用户登录状态变化
    • 当用户未认证时自动弹出登录界面
    • 认证成功后自动隐藏登录界面
  2. 无缝用户体验

    • 在后台静默检查认证状态
    • 保持用户操作的连续性
    • 避免不必要的界面跳转
  3. 状态管理集成

    • 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())
    }
}

工作机制

  1. 通知监听

    • 监听 Constants.Notifications.showPaywall 通知
    • 在 ContentView 根级别设置,实现全局覆盖
    • 通过 NotificationCenter 响应付费墙调用
  2. 与 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. 依赖注入架构

通过 @StateObjectenvironmentObject 实现了清晰的依赖注入模式,确保:

  • 单一数据源
  • 状态共享
  • 模块解耦

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 中的应用体现了以下架构优势:

  1. 集中式控制

    • showAuthView(): 在应用入口统一管理用户认证状态
    • showPaywallSheetWhenCalled(): 通过通知系统全局监听付费墙展示请求
    • 简化了各个子模块的实现复杂度,提供一致的用户体验
  2. 松耦合设计

    • 认证保护通过修饰器自动应用,子视图无需关心具体实现
    • 付费墙通过 AuthManager.actionGoPaywall() 与通知系统解耦
    • 业务逻辑与 UI 展示完全分离,便于测试和维护
  3. 灵活的付费保护策略

    • 全局通知方式: actionGoPaywall() + showPaywallSheetWhenCalled()
    • 视图级保护: requirePremium() 修饰器
    • 支持 RevenueCat 和 StoreKit2 双重方案
    • 可根据场景选择不同的展示方式(sheet/fullScreenCover)

开发效率提升

  • 快速集成: 只需在根视图添加两个修饰器即可获得完整的认证和付费基础设施
  • 统一管理: 所有认证和付费相关的状态都通过管理器集中处理
  • 代码复用: 修饰器和管理器可以在不同项目中复用
  • 调试友好: 通过通知系统可以轻松跟踪付费墙的触发和展示

ContentView 作为应用程序的核心入口,通过 showAuthView() 提供认证保护,通过 showPaywallSheetWhenCalled() 建立全局付费墙监听机制,配合 AuthManager.actionGoPaywall() 实现了完整的用户认证和商业化基础设施,为整个应用的功能模块奠定了坚实的架构基础。

Last updated on