MacCatalyst中NSUserActivity状态恢复异常,session.stateRestorationActivity始终为nil
Mac Catalyst应用重启后窗口状态恢复:session.stateRestorationActivity始终为nil的解决办法
针对你遇到的session.stateRestorationActivity始终为nil的问题,可以从以下几个方面排查和修复:
1. 完善Info.plist的场景状态恢复配置
确保UIApplicationSceneManifest下的场景配置正确启用了状态恢复:
- 确认
UIApplicationSupportsMultipleScenes设置为YES - 每个
UISceneConfiguration条目下添加UISceneStateRestoration字典:- 添加
UISceneRestorationEnabled并设置为YES - 添加
UISceneRestorationClass,值为你的SceneDelegate类名(比如YourApp.SceneDelegate)
- 添加
2. 确保NSUserActivity被正确填充并关联到场景
当前stateRestorationActivity(for:)直接返回scene.userActivity,但如果这个userActivity本身是nil,系统就无法保存恢复状态。需要在用户操作改变内容时主动更新场景的userActivity:
// 在内容变化时调用,比如ContentViewController中 func saveCurrentState() { let activityType = "com.yourapp.detail" // 替换为你注册的活动类型 let userActivity = NSUserActivity(activityType: activityType) // 存入需要恢复的数据,比如当前选中的内容ID userActivity.userInfo = ["selectedContentID": "123"] // 将活动关联到当前窗口场景 view.window?.windowScene?.userActivity = userActivity // 标记活动为当前需要保存的状态 userActivity.becomeCurrent() }
3. 调整场景配置逻辑
在application(_:configurationForConnecting:options:)中,不要仅依赖options.userActivities.first来选择场景配置。状态恢复的场景会话可能不会携带这个参数,建议补充对connectingSceneSession.stateRestorationActivity的判断:
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { var configurationName = "Default Configuration" // 同时检查session的恢复活动和options中的活动 let targetActivity = options.userActivities.first ?? connectingSceneSession.stateRestorationActivity if let activityType = targetActivity?.activityType { switch activityType { case .UserActivity.SystemActivityType, .UserActivity.TagActivityType, .UserActivity.ProjectActivityType: configurationName = "Detail Configuration" default: break } } return UISceneConfiguration(name: configurationName, sessionRole: connectingSceneSession.role) }
4. 给需要恢复的视图控制器设置恢复标识
系统需要通过restorationIdentifier来重建视图控制器层级,给你的ContentViewController及其他需要恢复的控制器添加标识:
class ContentViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() restorationIdentifier = "ContentViewController" // 如果导航控制器也需要恢复,同样设置其restorationIdentifier navigationController?.restorationIdentifier = "MainNavigationController" } }
5. 调试状态保存流程
在stateRestorationActivity(for:)中添加日志,确认系统是否调用了这个方法:
func stateRestorationActivity(for scene: UIScene) -> NSUserActivity? { print("State restoration activity requested: \(scene.userActivity)") return scene.userActivity }
如果该方法未被调用,说明系统未触发状态保存,可能是应用未进入正确的生命周期阶段(比如需要正常退出应用,而非强制杀死),或者场景配置存在问题。
内容的提问来源于stack exchange,提问作者Nikodem
相关产品推荐
相关产品推荐

