如何全局重写SwiftUI Alert 实现Debug模式下自动加时间无需修改每处实例
实现方案
核心思路
通过Method Swizzling钩子拦截UIAlertController的viewWillAppear:生命周期方法,仅在Debug环境下自动给弹窗内容拼接当前时间,全程不需要修改项目中已有的任意Alert调用代码,可全局生效。
代码实现
1. 核心钩子逻辑
#if DEBUG import UIKit extension UIAlertController { @objc static func loadSwizzle() { guard self == UIAlertController.self else { return } let originalSel = #selector(viewWillAppear(_:)) let swizzledSel = #selector(debug_addTimeToAlert) guard let originalMethod = class_getInstanceMethod(self, originalSel), let swizzledMethod = class_getInstanceMethod(self, swizzledSel) else { return } method_exchangeImplementations(originalMethod, swizzledMethod) } @objc private func debug_addTimeToAlert(animated: Bool) { // 触发系统原有viewWillAppear逻辑(方法已交换,此处调用对应原生实现) debug_addTimeToAlert(animated: animated) // 格式化当前时间 let df = DateFormatter() df.dateFormat = "yyyy-MM-dd HH:mm:ss" let currentTime = df.string(from: Date()) // 拼接时间到弹窗消息末尾,无原有消息则直接展示时间 let originMsg = message ?? "" message = originMsg + "\n\n调试时间:\(currentTime)" } } #endif
2. 全局注册生效
在App启动入口调用注册方法即可:
UIKit项目(AppDelegate)
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { #if DEBUG UIAlertController.loadSwizzle() #endif // 原有启动逻辑 return true }
SwiftUI项目(App入口结构体)
@main struct YourApp: App { init() { #if DEBUG UIAlertController.loadSwizzle() #endif } var body: some Scene { WindowGroup { ContentView() } } }
注意事项
- 所有逻辑都被
#if DEBUG包裹,正式Release包不会包含该代码,不会影响线上性能和用户体验 - 支持UIKit的
UIAlertController、SwiftUI的Alert/confirmationDialog等所有系统弹窗实现,无需修改原有弹窗调用代码 - 可根据需求自行调整时间格式、拼接位置(比如加到标题末尾)、展示样式
内容的提问来源于stack exchange,提问作者SalsaJJ
相关产品推荐
相关产品推荐

