import Expo import React import ReactAppDependencyProvider import BackgroundTasks @UIApplicationMain public class AppDelegate: ExpoAppDelegate { var window: UIWindow? var reactNativeDelegate: ExpoReactNativeFactoryDelegate? var reactNativeFactory: RCTReactNativeFactory? public override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil ) -> Bool { // 在应用启动完成前注册后台任务 if #available(iOS 13.0, *) { registerBackgroundTasks() } let delegate = ReactNativeDelegate() let factory = ExpoReactNativeFactory(delegate: delegate) delegate.dependencyProvider = RCTAppDependencyProvider() reactNativeDelegate = delegate reactNativeFactory = factory bindReactNativeFactory(factory) #if os(iOS) || os(tvOS) window = UIWindow(frame: UIScreen.main.bounds) factory.startReactNative( withModuleName: "main", in: window, launchOptions: launchOptions) #endif return super.application(application, didFinishLaunchingWithOptions: launchOptions) } // MARK: - Background Task Registration @available(iOS 13.0, *) private func registerBackgroundTasks() { let identifier = "com.anonymous.digitalpilates.task" // 注册后台任务处理器 // 必须在应用启动完成前注册,否则会崩溃 BGTaskScheduler.shared.register( forTaskWithIdentifier: identifier, using: nil ) { [weak self] task in // 尝试通知 BackgroundTaskBridge 处理任务 // 如果 bridge 不可用,标记任务完成 self?.handleBackgroundTask(task, identifier: identifier) } NSLog("[AppDelegate] 后台任务已在应用启动时注册: \(identifier)") } @available(iOS 13.0, *) private func handleBackgroundTask(_ task: BGTask, identifier: String) { // 尝试获取 BackgroundTaskBridge 实例来处理任务 // 如果 React Native bridge 还未初始化,则直接完成任务 guard let bridge = reactNativeFactory?.bridge, bridge.isValid else { NSLog("[AppDelegate] React Native bridge 未就绪,直接完成后台任务") task.setTaskCompleted(success: false) return } // 通过 bridge 查找 BackgroundTaskBridge 模块 DispatchQueue.main.async { if let module = bridge.module(for: BackgroundTaskBridge.self) as? BackgroundTaskBridge { // 通知 BackgroundTaskBridge 处理任务 NotificationCenter.default.post( name: NSNotification.Name("BackgroundTaskBridge.handleTask"), object: nil, userInfo: ["task": task, "identifier": identifier] ) } else { NSLog("[AppDelegate] BackgroundTaskBridge 模块未找到,完成后台任务") task.setTaskCompleted(success: false) } } } // Linking API public override func application( _ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:] ) -> Bool { return super.application(app, open: url, options: options) || RCTLinkingManager.application(app, open: url, options: options) } // Universal Links public override func application( _ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void ) -> Bool { let result = RCTLinkingManager.application(application, continue: userActivity, restorationHandler: restorationHandler) return super.application(application, continue: userActivity, restorationHandler: restorationHandler) || result } } class ReactNativeDelegate: ExpoReactNativeFactoryDelegate { // Extension point for config-plugins override func sourceURL(for bridge: RCTBridge) -> URL? { // needed to return the correct URL for expo-dev-client. bridge.bundleURL ?? bundleURL() } override func bundleURL() -> URL? { #if DEBUG return RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: ".expo/.virtual-metro-entry") #else return Bundle.main.url(forResource: "main", withExtension: "jsbundle") #endif } }