如何通过Swift/Objective-C获取macOS系统重启与系统更新的通知并执行后续操作?
嘿,这个需求在macOS开发里挺常见的,我来给你拆解清楚怎么实现👇
一、检测系统重启完成的通知
系统重启的检测分为两种场景:App运行时监听即将重启的信号,以及重启后App启动时判断是否刚完成重启。
1. 运行时监听系统即将重启的通知
你可以通过NSWorkspace提供的通知来捕获系统即将重启的事件,提前记录标记,方便重启后执行操作。
Swift 实现
// 在App启动阶段注册监听(比如AppDelegate的applicationDidFinishLaunching里) NotificationCenter.default.addObserver(forName: NSWorkspace.willRestartNotification, object: NSWorkspace.shared, queue: .main) { _ in // 把重启标记存入UserDefaults,重启后App启动时读取 UserDefaults.standard.set(true, forKey: "didTriggerSystemRestart") }
Objective-C 实现
// 在AppDelegate的applicationDidFinishLaunching方法中注册监听 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleSystemRestart:) name:NSWorkspaceWillRestartNotification object:[NSWorkspace sharedWorkspace]]; // 实现通知处理方法 - (void)handleSystemRestart:(NSNotification *)notification { [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"didTriggerSystemRestart"]; [[NSUserDefaults standardUserDefaults] synchronize]; }
2. 重启完成后执行操作(App启动时)
如果你的App设置了开机自启,重启后会自动启动,这时候读取之前存的标记就能判断是否刚完成重启:
Swift 实现
func applicationDidFinishLaunching(_ aNotification: Notification) { let didRestart = UserDefaults.standard.bool(forKey: "didTriggerSystemRestart") if didRestart { // 这里执行你需要的操作,比如同步数据、弹窗提示等 print("系统刚完成重启,执行后续操作") // 记得清除标记,避免下次启动重复执行 UserDefaults.standard.set(false, forKey: "didTriggerSystemRestart") } }
Objective-C 实现
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { BOOL didRestart = [[NSUserDefaults standardUserDefaults] boolForKey:@"didTriggerSystemRestart"]; if (didRestart) { NSLog(@"系统刚完成重启,执行后续操作"); // 执行你的业务逻辑 [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"didTriggerSystemRestart"]; [[NSUserDefaults standardUserDefaults] synchronize]; } }
备选方案:通过系统启动时间判断
如果你的App没有开机自启,下次手动启动时可以对比系统启动时间和App上次退出时间,来判断是否经历过重启:
Swift 实现
// 获取系统启动时间 func getSystemBootTime() -> Date? { var tv = timeval() var size = MemoryLayout<timeval>.stride let result = sysctlbyname("kern.boottime", &tv, &size, nil, 0) guard result == 0 else { return nil } return Date(timeIntervalSince1970: Double(tv.tv_sec) + Double(tv.tv_usec)/1_000_000) } // 在applicationDidFinishLaunching中判断 func applicationDidFinishLaunching(_ aNotification: Notification) { guard let bootTime = getSystemBootTime(), let lastQuitTime = UserDefaults.standard.object(forKey: "lastAppQuitTime") as? Date else { // 首次启动,记录当前时间 UserDefaults.standard.set(Date(), forKey: "lastAppQuitTime") return } if bootTime > lastQuitTime { print("系统刚完成重启,执行操作") } } // 在App退出时记录时间 func applicationWillTerminate(_ aNotification: Notification) { UserDefaults.standard.set(Date(), forKey: "lastAppQuitTime") }
二、检测系统更新完成的通知
系统更新的检测可以通过监听系统分布式通知,或者对比系统版本变化来实现,两种方式结合更可靠。
1. 监听系统更新完成的分布式通知
macOS的软件更新服务会发送分布式通知,你可以通过DistributedNotificationCenter监听:
Swift 实现
// 在App启动时注册监听 DistributedNotificationCenter.default().addObserver(forName: NSNotification.Name("com.apple.SoftwareUpdate.NotifyUpdateInstalled"), object: nil, queue: .main) { _ in print("系统更新已完成,执行后续操作") // 这里写你的业务逻辑 }
Objective-C 实现
// 在AppDelegate的applicationDidFinishLaunching中注册 [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(handleUpdateInstalled:) name:@"com.apple.SoftwareUpdate.NotifyUpdateInstalled" object:nil]; // 实现处理方法 - (void)handleUpdateInstalled:(NSNotification *)notification { NSLog(@"系统更新已完成,执行后续操作"); // 执行你的操作 }
2. 通过系统版本变化判断更新完成
有些更新可能不会触发通知(比如小版本更新),这时候可以记录上次运行时的系统版本,下次启动时对比:
Swift 实现
func applicationDidFinishLaunching(_ aNotification: Notification) { let currentOSVersion = ProcessInfo.processInfo.operatingSystemVersionString let lastOSVersion = UserDefaults.standard.string(forKey: "lastRecordedOSVersion") if let lastVersion = lastOSVersion, lastVersion != currentOSVersion { print("系统已更新,执行操作") } // 更新记录的版本 UserDefaults.standard.set(currentOSVersion, forKey: "lastRecordedOSVersion") }
Objective-C 实现
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { NSString *currentOSVersion = [[NSProcessInfo processInfo] operatingSystemVersionString]; NSString *lastOSVersion = [[NSUserDefaults standardUserDefaults] stringForKey:@"lastRecordedOSVersion"]; if (lastOSVersion && ![lastOSVersion isEqualToString:currentOSVersion]) { NSLog(@"系统已更新,执行操作"); } [[NSUserDefaults standardUserDefaults] setObject:currentOSVersion forKey:@"lastRecordedOSVersion"]; [[NSUserDefaults standardUserDefaults] synchronize]; }
三、一些重要注意事项
- 如果要在重启后自动执行操作,务必确保你的App已添加到系统设置的登录项中(系统设置 > 通用 > 登录项),否则重启后App不会自动启动。
- 分布式通知可能存在延迟或遗漏,建议结合版本对比的方式,提升检测的可靠性。
- 记得在App退出时移除通知观察者,避免内存泄漏(比如在
applicationWillTerminate中调用removeObserver:)。
内容的提问来源于stack exchange,提问作者Ajay
相关产品推荐
相关产品推荐

