You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中如何判断系统启动页完全消失以同步动画?

解决SwiftUI中启动页消失后Logo平滑动画的问题

要解决启动页淡出时Logo动画提前开始导致的重影问题,核心是准确捕获系统启动页完全消失的时机,而非依赖不可靠的固定延迟。以下是两种可靠的实现方案:

方案一:监听窗口可见通知

系统启动页是临时的系统窗口,当App的主窗口变为可见时,启动页已被完全移除。通过监听UIWindow.didBecomeVisibleNotification可以精准捕获这个时机:

import SwiftUI

struct ContentView: View {
    @State private var isLaunchFinished = false
    // 控制Logo位置的偏移量
    @State private var logoPositionOffset = CGSize.zero
    
    var body: some View {
        ZStack {
            // 主界面背景
            Color.systemBackground.edgesIgnoringSafeArea(.all)
            
            // 需要动画的Logo
            Image("AppLogo")
                .offset(logoPositionOffset)
                // 仅当偏移量变化时触发动画
                .animation(.easeInOut(duration: 0.6), value: logoPositionOffset)
        }
        .onAppear {
            NotificationCenter.default.addObserver(
                forName: UIWindow.didBecomeVisibleNotification,
                object: nil,
                queue: .main
            ) { _ in
                guard !isLaunchFinished else { return }
                isLaunchFinished = true
                // 启动Logo移动动画(示例:移动到顶部导航栏位置)
                logoPositionOffset = CGSize(width: 0, height: -120)
            }
        }
        .onDisappear {
            // 移除通知监听,避免内存泄漏
            NotificationCenter.default.removeObserver(
                self,
                name: UIWindow.didBecomeVisibleNotification,
                object: nil
            )
        }
    }
}

方案二:利用UIViewController的viewDidAppear回调

SwiftUI的onAppear会在视图加载完成后立即触发,但此时启动页可能尚未消失。而UIKit中UIViewController的viewDidAppear方法,会在界面完全显示、启动页彻底消失后调用。我们可以通过UIHostingController包装SwiftUI视图来获取这个时机:

1. 自定义HostingController

import SwiftUI

class MainHostController: UIHostingController<ContentView> {
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        // 发送自定义通知告知启动完成
        NotificationCenter.default.post(
            name: NSNotification.Name("LaunchScreenDidDisappear"),
            object: nil
        )
    }
}

2. 在App入口使用自定义HostController

@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            MainHostController(rootView: ContentView())
        }
    }
}

3. 在ContentView中监听通知触发动画

struct ContentView: View {
    @State private var isLaunchFinished = false
    @State private var logoPositionOffset = CGSize.zero
    
    var body: some View {
        ZStack {
            Color.systemBackground.edgesIgnoringSafeArea(.all)
            Image("AppLogo")
                .offset(logoPositionOffset)
                .animation(.easeInOut(duration: 0.6), value: logoPositionOffset)
        }
        .onReceive(
            NotificationCenter.default.publisher(
                for: NSNotification.Name("LaunchScreenDidDisappear")
            )
        ) { _ in
            guard !isLaunchFinished else { return }
            isLaunchFinished = true
            logoPositionOffset = CGSize(width: 0, height: -120)
        }
    }
}

关键注意事项

  • 绝对不要用固定延迟(如DispatchQueue.main.asyncAfter(deadline: .now() + 0.5)):不同设备启动速度差异大,会导致动画时机不准确,要么延迟要么仍有重影。
  • 必须标记isLaunchFinished状态:避免重复触发动画(比如App从后台回到前台时)。

内容的提问来源于stack exchange,提问作者Mark

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 22:10:28